八、Linux进程(二)

5.exec函数族

1.让父子进程来执行不相干的操作

2.能够替换进程地址空间的代码.text段

3.执行另外的程序,不需要创建额外的的地址空间

4.当前程序中调用另外一个应用程序

返回值:

如果函数运行成功不返回

如果执行失败,打印错误信息,退出子进程

它们的一般规律如下:

l (list) 命令行参数列表

p (path) 搜素file时使用path变量

execl函数

指定执行目录下的程序

int execl(const char *path, const char *arg, ... /* (char *) NULL */);

/*

path : 要执行程序的路径(最好是绝对路径)

变参arg : 要执行的程序需要的参数

    第一位arg: 占位(写什么都可以,最好和程序名字一样)

    后边的arg: 命令的参数

    参数写完之后:null

一般执行自己写的程序

*/


在子进程中使用execl函数

子进程执行到execl函数就不再执行子进程中execl函数后面的代码

再加上一行for循环:

for循环为父进程所执行:


execlp函数

执行PATH环境变量能够搜索到的程序

int execlp(const char *file, const char *arg, ... /* (char *) NULL */);

/*

file :执行的命令名字

第一个arg:占位

后边的arg:命令的参数

参数写完之后:NULL

执行系统自带的程序:/bin/xx */ ps aux

*/


更改execlp函数以及其参数更改为系统自带的程序


6.孤儿进程和僵尸进程

孤儿进程

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

为了释放子进程的占用的系统资源:

进程结束之后,能够释放用户区空间

释放不了PCB,必须由父进程释放

先打印父进程的代码,过1s之后打印子进程的代码

且可发现子进程的ppid(1458)不是父进程的pid(2306)

再去查看进程1458的信息,发现子进程已被init进程回收(孤儿被收养)

僵尸进程

一个比较特殊的状态,当进程退出父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸进程。僵尸进程会在以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。

是一个已经死掉了的进程

 子进程退出后,父进程还在工作,没时间回收子进程,此时子进程为僵尸进程

这时查看进程信息ps aux

第一行表示父进程(能被kill),第二行表示僵尸进程(不能被kill)

这时kill父进程

发现退出程序退出

 且ps aux之后发现不会再有僵尸进程

7.进程回收

wait 阻塞函数

函数作用:

1.阻塞父进程并等待子进程退出

2.回收子进程残留资源

3.获取子进程结束状态(退出原因)

pid_t wait(int *wstatus);

返回值:

        ‐1 : 回收失败,已经没有子进程了

        >0 : 回收子进程对应的pid

参数 :

           status判断子进程如何退出状态

          1.WIFEXITED(status):为非0 ,进程正常结束

               WEXITSTATUS(status) 如上宏为真,使用此宏,获取进程退出状态的参数

          2.WIFSIGNALED(status):为非0,进程异常退出

               WTERMSIG(status):如上宏为真,使用此宏,取得使进程终止的那个信号的编号

调用一次只能回收一个子进程

 在父进程中执行wait阻塞函数

先阻塞父进程中的代码并执行子进程中的代码

判断子进程为正常退出

返回值为代码最后的return所返回的值


修改代码,使子进程循环打印

kill子进程

判断出子进程为异常退出

waitpid函数

函数作用:同 wait 函数

pid_t waitpid(pid_t pid, int *status, int options);

参数:

        1.pid: 指定回收某个子进程

                pid == ‐1 回收所有子进程

                        while( (wpid=waitpid(‐1,status,0)) != ‐1)

                pid > 0 回收某个pid相等的子进程

                pid == 0 回收当前进程组的任一子进程

                pid < 0 子进程的PID取反(加减号)

        2.status: 子进程的退出状态,用法同wait函数

        3.options:设置为WNOHANG,函数非阻塞,设置为0,函数阻塞

返回值:

        >0 :返回清理掉的子进程ID

        ‐1 :回收失败,无子进程

        如果为非阻塞

        =0 :参数3WNOHANG,且子进程正在运行

8.vfork创建进程

vfork也可以创建进程,与fork有什么区别呢?

区别一:vfork可以直接使用父进程存储空间,不拷贝

区别二:vfork可以保证子进程先运行,当子进程调用exit退出后,父进程才执行


如果此时为fork函数

此时,父子进程轮流抢占资源

若此时为vfork函数

会先执行子进程

验证区别二:vfork可以保证子进程先运行,当子进程调用exit退出后,父进程才执行

代码改进:

在子进程中每打印一次cnt加1,直到打印三次之后,退出子进程

且在打印父进程代码时,cnt的值仍然为3

验证区别一:vfork可以直接使用父进程存储空间,不拷贝

9.进程退出

正常退出

1.main函数调用return

2.进程调用exit(),标准C

3.进程调用 _exit()或者 _Exit(),属于系统调用

补充:

4.进程最后一个线程返回

5.最后一个线程调用pthread_exit

异常退出

1.调用abort函数

2.当进程收到某些信号时,比如ctrl +C

3.最后一个线程对取消(cancellation)请求做出相应

不管进程如何终止,最后都会执行内核中的同一段代码,这段代码和相应进程关闭所有打开描述符,释放它所使用的存储器等。

对上述任一一种终止情形,我们都希望终止进程能够通知其父进程它是如何终止的。对于三个终止函数(exit, _exit和 _ Exit),实现这一点的方法是,将其退出状态(exit status)作为参数传送给函数,在异常终止情况下,内核(不是进程本身)产生一个指示其异常终止原因的终止状态(termination status)。在任意一种情况下,该终止进程的父进程都能用waitwaitpid函数取得终止状态。

#include <stdlib.h>

void exit(int status);

#include <unistd.h>

void _exit(int status);

#include <stdlib.h>

void _Exit(int status);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值