进程的相关操作fork vfork

一、进程的查看(ps  top)

ps指令

top指令

二,进程标识符pid的查看(  getpid()   getppid() )

进程标识符:进程标识符(PID)是一个进程的基本属性,其作用类似于每个人的身份证号码。根据进程标识符,用户可以精确地定位一个进程。一个进程标识符唯一对应一个进程,而多个进程标识符可以对应同一个程序。

0标识系统的调度进程,1表示系统的初始化进程。

函数原型:

        pid_t  getpid(void);//获取当前进程的pid

        pid_t  getppid(void);//获取当前进程的父进程的pid

返回值:

        进程的标识符

用例:

pid_t pid;
pid=getpid();
printf("pid=%d\n",pid);

三、进程的创建(fork()   vfork())

1、fork函数

函数原型:

        pid_t   fork(void);

返回值:

        函数调用成功,函数返回两次,返回值为0,代表当前进程为进程,返回值为非负数,代表当前进程为父进程。调用失败,返回-1。

用例:

 pid_t pid=fork();
 if(pid>0){
        printf("父进程\n");
 }
 else if(pid==0){
        printf("子进程\n");
 }

2、vfork函数

vfork函数需要与exit(),_exit(),_Exit,wait()等函数使用。第四节会讲数进程的退出。

函数原型:

        pid_t   vfork(void);       

返回值:

        函数调用成功,函数返回两次,返回值为0,代表当前进程为进程,返回值为非负数,代表当前进程为父进程。调用失败,返回-1。

用例:

 int i=3;
 pid_t pid=vfork();
 if(pid>0){
        wait(NULL);
        printf("父进程\n");
 }
 else if(pid==0){
        while(i--){
           printf("子进程\n");
        }
        exit(0);
 }

 3、fork与vfork的异同

相同点:二者的用法都一样,返回值也相同。

区别:

        1、在fork中,父进程与子进程公用存储空间,当子进程要对数据段的数据改变时在拷贝一份数据。而在vfork中子进程直接使用父进程的存储空间,不拷贝,此处需要要简单了解一下程序在内存中是怎样存储的。

命令行参数和环境变量
.....................
堆(malloc等开辟的空间)
bss段(未被初始化的数据)
数据段(已经初始化的数据)
代码段(正文内容)

        2、vfork保证子进程先执行,子进程结束后,父进程才执行。fork中子进程和父进程的执行顺序是由系统的调度决定的,谁先执行轮到谁执行了都是系统调度进程决定的。

        下面用代码来展示二者的区别。下面两段代码都在子进程中对变量a的值+1了,但在父进程中a的值却不一样,在fork中,父进程中a的值没有变,在子进程中+1了,变为了11,在vfork语句中,同样在子进程中对a的值+1了,但是父进程的值也变为了11,原因就是上述的区别1。在fork语句中,子进程对变量a的值进行改变时,会拷贝一份在自己的存储空间,此时在父进程和子进程中各有一块区域来存放变量a,是两个变量了。而在vfrok语句中,父子进程共用存储空间,所以子进程改变了a的值,父进程打印出来的a的值也跟着改变了,他们用的是一个a。

fork代码:

int a=10;
pid_t pid=fork();
if(pid>0){
        printf("father  a=%d\n",a);
}
else if(pid==0){
        a++;
        printf("son     a=%d\n",a);
}

运行结果:

father  a=10
son     a=11

vfork代码:

int a=10;
pid_t pid=vfork();
if(pid>0){
        wait(NULL);
        printf("father");
}
else if(pid==0){
        a++;
        printf("son");
        exit(3);
}
printf("\t a=%d\n",a);

运行结果:

son    a=11
father  a=11

四、父进程等待子进程的退出

        在实际的应用过程过,父进程需要知道子进程的状态以及完成情况,所以需要等待子进程的状态。需要使用的函数为wait,waitpid和exit,_exit,_Exit。

僵尸进程:子进程的退出状态不被收集,就会变为僵尸进程。

函数原型:

pid_t   wait(int *status)

 void _exit(int status);

参数说明:

        status是一个整型指针,子进程的退出状态就存放在它所指向的地址中。为NULL时表示不关心子进程的退出状态。

用例:

int a=10;
int *status;
pid_t pid=vfork();
if(pid>0){
        wait(status);
        printf("father  status:%d\n",WEXITSTATUS(status));
}
else if(pid==0){
        a++;
        printf("son");
        exit(3);
}
printf("\t a=%d\n",a);

以上述代码为例,wait会阻塞父进程的运行,wait后面的语句不会执行,直到子进程执行完,exit发送退出状态码,wait收集到这个状态码,父进程才会执行。WEXITSTATUS函数可以解析这个状态码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值