Linux进程概论

一、进程概念

概念:程序的一个执行实例/正在执行的程序/能分配处理器并由处理器执行的实体。

内核观点:担当分配系统资源(CPU时间,内存)的实体。

进程的两个基本元素是程序代码(可能被执行相同程序的其他进程共享)和代码相关联的数据集。进程是一种动态描述,但是并不代表所有的进程都在运行。(进程在内存中因策略或调度需求,会处于各种状态)。

二、进程控制块

广义上,所有的进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。

进程控制块(PCB):每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。

task_struct是Linux内核的一种数据结构,它会被装载到RAM里并且包含着进程的信息。 每个进程都把它的信息放在 task_struct 这个数据结构里,task_struct 包含了这些内容:    

标识符 : 描述本进程的唯一标识符,用来区别其他进程(进程ID(PID)、父进程ID(PPID))。

状态    :任务状态,退出代码,退出信号等。       

优先级 :相对于其他进程的优先级。    

程序计数器:程序中即将被执行的下一条指令的地址。    

内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。   

上下文数据:进程执行时处理器的寄存器中的数据。    

I/O状态信息:包括显式的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。    

记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。   

可以在 include/linux/sched.h 里找到task_struct。 所有运行在系统里的进程都以 task_struct 链表的形式存在内核⾥里。进程的信息可以通过 /proc 系统文件夹查看。要获取PID为400的进程信息,你需要查看 / proc/400 这个文件夹。大多数进程信息同样可以使用top和ps这些用户级工具来获取。

三、进程内存映像

进程的内存映像是指内核在内存中如何存放可执行程序文件。在将程序转化为进程的过程中,操作系统将可执行程序从硬盘复制至内存中,其布局如下:

                           

 可执行程序与进程内存映像的区别:    

1.可执行程序位于磁盘中而内存映像位于内存  

2.可执行程序没有堆栈,因为程序被加载到内存中才会分配堆栈  

3.可执行程序虽然也有未初始化数据段但它并不被存储在位于硬盘中的可执行文件中

4.可执行程序是静态的、不变的,而内在映像随着程序的执行是在动态变化的,比如数据段随着程序的执行要存储新的变量值,栈在函数调用时也是不断在变化中

四、进程状态

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里进程有时候也叫做任务)。

运行状态R(running):它表明进程要么是在运行中要么在运行队列里。

睡眠状态S(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。

磁盘休眠状态D(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待I/O的结束。

僵死状态Z(Zombies):当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死进程。僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

挂起状态T (stopped):进程被暂停,需要通过其它进程的信号才能被唤醒。导致这种状态的原因有两种。其一是受到相关信号(SIGSTOP,SIGSTP,SIGTTIN或SIGTTOU)的反应。其二是受到父进程ptrace调用的控制,而暂时将处理器交给控制进程。

跟踪状态t (tracing stop):当进程正在被跟踪时,它处于这个特殊的状态。“正在被跟踪”指的是进程暂停下来,等待跟踪它的进程对它进行操作。

退出状态/死亡状态X (dead):是内核运行 kernel/exit.c 里的 do_exit() 函数返回的状态。这个状态只是一个返回状态。

五、进程优先级

进程 cpu资源分配就是指进程的优先权(priority)。优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。还可以把进程运行到指定的 CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

Linux下执行ps -l命令输出下面内容:

UID : 代表执行者的身份

PID : 代表这个进程的代号

PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号

PRI :代表这个进程可被执行的优先级,其值越小越早被执行

NI :代表这个进程的nice值,其表示进程可被执行的优先级的修正数值。

更改进程的nice值:

修改nice后,将会使得PRI变为:PRI(new)=PRI(old)+nice。这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。设置的优先权等级的范围从-20-19,其中-20最高,19最低

1.一开始执行程序就指定nice值:nice

2.调整已存在进程的nice值:renice

3.可以用top命令更改已存在进程的nice

六、进程执行

当进程执行时,它会被装载进虚拟内存,为程序变量分配空间,并把相关信息添到 task_struct里。

1.创建进程的方法:fork()和execve()。它们都是系统调用,但它们的运行方式有点不同。

 要创建一个子进程可以执行fork()系统调用。然后子进程会得到父进程中数据段,栈段和堆区域的一份拷贝。子进程独立可以修改这些内存段。但是文本段是父进程和子进程共享的内存段,不能被子进程修改。    

如果使用execve()创建一个新进程。这个系统调用会销毁所有的内存段去重新创建一个新的内存段。然而,execve()需要一个可执行文件或者脚本作为参数,这和fork()有所不同。execve()和fork()创建的进程都是运行进程的子进程。

2.僵尸进程:一个子进程在其父进程没有调用wait()或waitpid()的情况下退出。这个子进程就 是僵尸进程。如果其父进程还存在而一直不调用wait,则该僵尸进程将无法回收,等到其父 进程退出后该进程将被init回收。

3.孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

七、进程终止

进程终止的方式有8种,前5种为正常终止,后三种为异常终止:      

1.从main函数返回;      

2.调用exit函数;      

3. 调用_exit或_Exit;

_exit和_Exit立即进入内核,而exit则要先做一些清理 工作(调用执行各终止处理程序,关闭所有标准I/O流),再进入内核。    

4.最后一个线程从启动例程返回;      

5.最后一个线程调用pthread_exit;      

6.调用abort函数;      

7.接到一个信号并终止;      

8.最后一个线程对取消请求做出响应。

八、进程标识符

每个进程都有非负的整形表示唯一的进程ID。一个进程终止后,其进程ID就可以再次使用了。如下是几个典型进程的ID及其类型和功能。

pid_t getpid(void);          返回值:  调用进程的进程ID

pid_t getppid(void);        返回值:调用进程的父进程ID

uid_t getuid(void);          返回值:调用进程的实际用户ID

uid_t geteuid(void);        返回值:调用进程的有效用户ID

gid_t getgid(void);          返回值:调用进程的实际组ID

gid_t getegid(void);        返回值:调用进程的有效组ID




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值