现代操作系统学习笔记——posix标准中的进程管理

posix标准

定义操作系统应该为应用程序提供的接口标准。


进程管理中比较重要的几个系统调用如下:

pid = fork():创建与父进程相同的子进程。

pid = waitpid(pid,&statloc,options):等待一个子进程终止。

s = execve(name,argv,environp):让进程执行新的代码。

exit(status):终止进程执行并返回状态。


下面给出现代操作系统中给出的实例:

UNIX中的shell

#define TRUE 1

while(TRUE){
    //在屏幕上显示提示符
    type_prompt();  
    //从终端读取输入
    read_command(command,parameters);
    if(fork()!=0){
    //等待子进程退出
     waitpid(-1,&status,0);
     }else{
     //执行键入的命令
     execve(command,parameters,0);
     }
}

该shell在键入一个命令后会调用fork()创建一个子进程,由这个子进程执行键入的命令。

fork()系统调用会创建一个原有进程的精确副本,换句话说,子进程将执行父进程剩余的代码,即fork()之后的代码,并且子进程默认父进程之前的代码已经执行完毕,这些代码是只读的,所以两个进程是共享的,但子进程与父进程有不同的堆栈段以及数据段,只是内容与父进程一致,在一些资料上,会说fork()系统调用返回两个值,其实不够准确,我的理解是,对于父进程,fork()返回子进程的进程标识符,对于子进程,返回0,这两个进程的执行将会是并发的,谁先谁后由操作系统决定,对于子进程,将会执行execve函数。


execve系统调用有三个参数:将要执行的文件名称,指向变量数组的指针(存放键入指令的参数),指向环境数组的指针(将诸如终端类型以及根目录等信息传送给程序),该系统调用实质上是exec系统调用,该调用没有创建新的进程,只是替换了原来进程的上下文,原进程的代码段、数据段、堆栈段被新的进程替换。意味着子进程执行完该函数后就会终止。


对于父进程,将会执行waitpid系统调用,第一个参数为子进程的进程标识符,若为-1,表示任何子进程结束就运行父进程,否则,必须在具体子进程结束后,在运行父进程,第二个参数指向存放子进程退出状态的容器地址,第三个参数为选项,可以选择执行一些功能。


子进程完成后会使用exit系统调用,该系统调用返回一个参数,为退出状态(0到255),该参数通过waitpid中的第二个参数返回给父进程。


为什么UNIX不像windows那样,将fork和exec合并为一个函数?

在网上看到了许多说法,我个人比较认同的是——这是UNIX的设计理念,由于与exec类似的函数有很多,如果将fork与exec合并,会造成大量的代码重复,与UNIX设计理念不合。

猜你喜欢

转载自blog.csdn.net/dhaiuda/article/details/79380337