【linux】 进程概念

冯诺依曼体系结构

冯诺依曼—奠定了现代计算机的硬件体系结构
现代计算机的五大硬件单元
输入设备:键盘,鼠标
输出设备:显示器
存储器;内存(易失性,一旦掉电,数据将全部丢失)
运算器;CPU(中央处理器)
控制器;CPU

操作系统:

目的:让计算机更好用
功能:统筹管理计算机上的软硬件资源,提供良好的执行环境
如何管理软硬件资源:先描述,后组织
库函数和系统调用接口的关系:
上下级的调用关系,库函数就是对系统调用接口的一层封装
操作系统:搞管理的软件
对下管理软硬件资源,对上提供良好的执行环境
如何管理:先描述,再组织进行管理

进程概念

进程是什么?
进程就是运行起来的程序—用户层面的理解
 程序运行需要将代码数据加载到内存中,操作系统上运行了很大的程序,操作系统就必须去管理这些程序的运行,先描述再组织进行管理
进程就是操作系统对运行程序的描述信息-进程描述符-统称PCB—操作系统层面的理解
 linux----struct task_struct

task_struct内容分类

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

操作系统可以看成某单位领导A
PCB可以看成其下属B的档案
实际进程为下属本人B
A提拔B,会先看B的档案,然后可以根据档案详细的描述信息来决定是否提拔B
如何查看进程

大多数进程信息可以通过ps或者top来进行查询
getpid

如何创建进程

fork():通过复制调用进程创建子进程
复制:复制的是父进程pcb,因此代码共享,数据独有
返回值:通过返回值对父子进程分流
  对于父进程,返回的是子进程的pid>0
  对于子进程,返回的是0

  1 //进程创建进程
  2 //通过复制调用进程,创建一个新的进程(子进程)
  3 
  4 #include<stdio.h>
  5 #include<unistd.h>
  6 
  7 int main(){
  8  // pid_t fork(void);
  9  printf("dad:pid[%d]\n",getpid());          打印的是父进程的pid                                                   
 10   fork();
 11   printf("haha!!  pid[%d]\n",getpid());
 打印两次pid分别是父子进程的pid
 12   return 0;
 13 }

 
 打印
dad:pid[7006]
haha!!  pid[7006]
haha!!  pid[7007]


  1 //进程创建进程                                                                                 
  2 //通过复制调用进程,创建一个新的进程(子进程)
  3                                               
  4 #include<stdio.h>                             
  5 #include<unistd.h>                            
  6                                               
  7 int main(){                                                 
  8  // pid_t fork(void);                                       
  9    printf("dad:pid[%d]\n",getpid());                        
 10                                                             
 11    pid_t pid= fork();                                       
 12    if(pid<0)                                                
 13      printf("fork error\n");                                
 14    else if(pid==0){                                         
 15      //child                                                
 16      printf("I am child!!!\n pid:%d\n",getpid());           
 17    }else{                                                   
 18      //parent                                               
 19     printf("I am parent!!!!\n pid:%d\n",getpid());          
 20    }                                                        
 21    printf("haha!!  pid[%d]\n",getpid()); 22    return 0;
 23 }  
打印
dad:pid[7262]
I am parent!!!!
 pid:7262
haha!!  pid[7262]
I am child!!!
 pid:7263
haha!!  pid[7263]
进程状态

运行态(R):
可中断

R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */

R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
** X死亡状态(dead )**:这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
Z(zombie)-僵尸进程:进程退出了但是资源没有完全释放,仍处于僵死状态
  产生原因:子进程先于父进程退出,为了保存退出返回值在pcd中,这时候操作系统
不会随意释放所有资源,因为父进程可能关心子进程退出原因,但是父进程可能没有及时关注这个通知,导致子进程退出后资源一直无法完全释放,处于僵死状态,这就使子进程变成僵尸进程
   危害:资源泄露,僵尸进程过多导致新进程无法创建
   干掉父进程(退出原因的保存已经毫无意义)
  &emsp如何避免:进程等待
孤儿进程:父进程先于子进程退出,子进程成为孤儿进程,运行在后台(即变成后台进程),父进程成为1号进程

 守护进程:特殊(脱离与终端+会话的关联)的孤儿进程

CPU报100%可能的原因

遇到了一个纯粹数据运算的死循环

一个进程杀不死什么原因

是一个僵尸进程

进程优先级

查看进程优先级:ps -l
IO密集型程序/CPU密集型程序
nice值范围:-20~19
设置方法:renice -n ni_val -p pid
  nice -n ni_val ./main
竞争性:进程之间对CPU进行争抢
独立性:进程之间应该具备独立性,保证进程稳定运行
并发:多个进程在cpu上切换调度运行
并行:CPU资源足够多,进程就可以同时运行

环境变量

环境变量:存有操作系统运行环境参数的变量–系统设置更加方便

常见环境变量

PATH: 指定命令的搜索路径
HOME: 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL: 当前Shell,它的值通常是/bin/bash

相关命令

echo:显示某个环境变量值
export: 设置一个新的环境变量
env: 显示所有环境变量
unset: 清除环境变量
set: 显示本地定义的shell变量和环境变量

环境变量在代码中的获取使用及全局特性
    1 //环境变量在代码中的获取
    2 #include<stdio.h>
    3 #include<stdlib.h>
    4 #include<unistd.h>
    5 
    6 int main(int argc,char* argv[],char *env[]){
    7   int i;
    8   for(i=0;env[i]!=NULL;++i){                                                                 
    9     printf("env[%d]=[%s]\n",i,env[i]);
   10   }
   11   return 0;
   12 }


打印
env[0]=[XDG_SESSION_ID=9]
env[1]=[HOSTNAME=localhost.localdomain]
env[2]=[SELINUX_ROLE_REQUESTED=]
env[3]=[TERM=xterm]
env[4]=[SHELL=/bin/bash]
env[5]=[HISTSIZE=1000]
env[6]=[SSH_CLIENT=192.168.224.1 49858 22]
env[7]=[SELINUX_USE_CURRENT_RANGE=]
env[8]=[SSH_TTY=/dev/pts/1]
env[9]=[USER=muxiaoxi]
env[10]=[LD_LIBRARY_PATH=:/home/muxiaoxi/.VimForCpp/vim/bundle/YCM.so/el7.x86_64]
env[11]=[LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:]
env[12]=[SSH_AUTH_SOCK=/tmp/ssh-ag5B2xQ2ww/agent.4958]
env[13]=[MAIL=/var/spool/mail/muxiaoxi]
env[14]=[PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/muxiaoxi/.local/bin:/home/muxiaoxi/bin]
env[15]=[PWD=/home/muxiaoxi/linux/第三章进程概念]
env[16]=[LANG=zh_CN.UTF-8]
env[17]=[SELINUX_LEVEL_REQUESTED=]
env[18]=[HISTCONTROL=ignoredups]
env[19]=[SHLVL=1]
env[20]=[HOME=/home/muxiaoxi]
env[21]=[LOGNAME=muxiaoxi]
env[22]=[SSH_CONNECTION=192.168.224.1 49858 192.168.224.129 22]
env[23]=[LESSOPEN=||/usr/bin/lesspipe.sh %s]
env[24]=[XDG_RUNTIME_DIR=/run/user/1000]
env[25]=[_=./env]
env[26]=[OLDPWD=/home/muxiaoxi/linux]

程序地址空间
程序地址空间内核空间 1G
环境变量/运行参数
共享区
用户空间 3G
初始化全局数据
未初始化全局数据
代码段

程序地址空间其实是虚拟地址空间
结构体:进程的内存描述符

mm_struct{
    ulong size;//内存的大小
    code_start;//代码开始
    code_end;//代码结束
    data_start;//数据开始
    data_end;//数据结束
}
虚拟地址空间和页表共同使用:

  提高内存利用率,增加内存访问控制
  保证进程之间的独立性

页表:当用程序访问一个虚拟地址时,首先必须将虚拟地址转换成物理地址,然后处理器才能解析地址访问请求。地址的转换工作需要通过查询页表完成

Linux中使用三级页表完成地址转换。利用多级页表能够节约地址转换所需要占用的存放空间。Linux对所有体系结构,包括那些不支持三级页表的体系结构 都使用三级页表管理 ,因为使用三级页表结构可以利用 “最大公约数” 的思想—一种设计简单的体系结构,可以按照需要在编译时简化使用页表的三级结构


为什么要使用结构体描述一段内存(即页表及虚拟地址空间),而不是直接使用物理内存

直接使用物理内存时,内存使用率低,且缺乏内存访问控制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值