版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、ESD_DAY032_ElvisUNIX/LINUX系统下的C高级编程A.N.E.K1 .进程管理1.1 进程的终止_exit()/_Exit()函数:功能:立即终止当前正在运行的进程。格式:#include void _exit(int status);#include void _Exit(int status);注意:_exit ()和Exit ()函数功能上完全相同;在终止进程时,会自动关闭属于该进程的文件描述 符,会给该进程的父进程发送SIGCHLD信号,该进程的所有子进程会重新认定新的父进程为init ;参数值会被返回给父进程作为该进程终止时的退出状态信息,父进程需要调用wait系
2、列函数来获取该数据。返回值:无返回值exit()函数:功能:引起正常进程的终止。格式:#include void exit(int status);注意:将参数status&0377之后的数据返回给当前进程的父进程自动调用所有被atexit ()和on_exit ()函数注册过的函数,一般用于处理善后工作,然后 终止进程。返回值:无返回值atexit ()函数:功能:对参数指定的函数进程注册。格式:#include int atexit(void(*function)(void);注意:所有被该函数注册过的函数会在正常终止时被调用(调用exit函数和执行 main函数中的return )。返回
3、值:成功返回0,失败返回非零。wait ()函数功能:主要用于挂起当前正在调用的进程,直到有一个该进程的子进程终止为止,可用于回收子进程,当有多个子进程时,随机回收一个。格式:#include #include pid_t wait(int *status);注意:参数status指针表示获取子进程的终止状态并放到status这个变量中;如果参数为空时,表示不关心子进程的退出状态;如果参数不为空时,该函数会将进程的状态信息存储在参数指定的int类型空间中,解析该状态需要借助以下带参宏,传递给宏的参数必须是整数自己,而不是指向它的指针:WIFEXITED(*status):如果子进程正常终止 (
4、exit ()或exit ()或 return ),则返回 true ; (wait if exited )WEXITSTATUSstatus ):获取子进程的退出码,所谓的退出码就是子进程调用exit/_exit/_Exit 函数的参数或者main函数的返回值的低8位,因此传递给这三个函数的参数和main函数的返回值最好不要超过【-128,127 】;(wait exit status )WIFSIGNALED status ):判断子进程是否异常终止;如果是则通过WTERMSIG ( status )宏获取导致子进程异常终止的信号。返回值:成功返回终止的子进程的进程号,失败返回-1。1.2
5、 父进程在创建若干个子进程后调用wait函数a.若所有子进程都在运行,则父进程阻塞(可视为睡眠) ,直到有子进程终止b.若有一个子进程终止,则返回该子进程的PID并通过status参数(若非空)则输出其终止状态;c.若没有需要等待子进程,则返回 -1,置errno为ECHILD (可作为多个子进程全部返回 的标志),表示所有子进程回收完毕;d.如果有一个子进程在wait函数被调用之前已经终止,则将处于僵尸状态,此时调用wait函数会立即返回,同时取得该子进程的终止状态并通知父进程回收其资源;由此可见wait函数主要完成三个任务:A.阻塞父进程的运行,直到子进程终止再继续,停等同步(即等待子进程
6、处理结束);B.获取子进程的PID和终止状态,使父进程了解哪个子进程终止了及其终止原因;C.为子进程收尸,防止大量的僵尸进程存在于内核而耗费系统资源;1.3 status 的使用 int status ; /定义变量以装载子进程退出状态pid_t pid=wait (&status ); 阻塞父进程,等待子进程结束; if - -1=pid ) perror (wait ); exit (EXIT_FAILURE);if (WIFEXITED(status)printf (%d 子进程正常终止,退出码 %dn ” ,pid,WEXITSTATUS(status);else*printf( d
7、子进程异常终止,终止信号 dn ,pid,WTERMSIG(status);*使用wait函数及其相关宏回收子进程并判断其退出状态#include#include#include#include int main()pid_t pid=fork();if(-1=pid)perror(fork);return -1;if(0=pid)int status=0x12345678;0xprintf(这是子进程d,将以%#x状态退出n,getpid(),status); /#x 表示在打印时显示/return status;/exit(status);exit(status);_Exit(status
8、); /return/exit/_exit/_Exit结果相同printf(这是父进程,等待子进程n);int status;pid=wait(&status);printf(父进程发现 %d 进程以 %#x 状态退出 n,pid,WEXITSTATUS(status);return 0;1.4 waitpid 函数waitpid 函数使用时引入头文件 sys/types.h,sys/wait.h 功能:等待并回收任意或特定的子进程,。格式:#include #include pid_t waitpid(pid_t pid , int*status , int options);注意:第一个参
9、数:取小于-1的数,表示等待并回收特定进程组 (一群子进程的父进程的 PID,由-PID 标识)的任意子进程;等于-1 ,等待并回收任意的子进程,相当于 wait函数;等于0,等待并回收与调用 进程同进程组的任意子进程;大于0的数,等待并回收特定的子进程(pid标识);第二个参数:status ,输出子进程的终止状态,可置 NULL;第三个参数:options :取0,阻塞模式,若所等子进程仍在运行,则阻塞,直到其终止;取WNOHANG , 非阻塞模式,若所等待子进程仍在运行,并不阻塞,而是立即返回 0;*返回值:成功返回终止的子进程的进程号,失败返回-1。*使用waitpid函数等待并回收指
10、定的子进程#include#include#include int main()pid_t pids3; /创建一个数组来存放创建多个子进程int i=0;for(i=0;i3;i+)/使用循环创建多个子进程pidsi=fork();if(-1=pidsi) perror(fork);return -1; if(0=pidsi)printf(子进程:我是子进程 d,我要退出了 n,getpid();return 0;for(i=0;i3;i+)printf(父进程:我要等待%d进程n,pidsi);pid_t pid=waitpid(pidsi,NULL,0); / 根据 pidsi来回收指定
11、的子进程 if(-1=pid)perror(waitpid);return -1;printf(父进程:发现%d进程退出了 n,pid);return 0;*使用waipid函数的非阻塞选项回收子进程#include#include#include#include int main()pid_t pid=fork();if(-1=pid) perror(fork);return -1;if(0=pid) printf(子进程:采集数据开始n);/模拟采集sleep(5);printf(子进程:采集数据完成n);return 0;/pid=wait(NULL);/pid=waitpid(-1,N
12、ULL,0);/ 和 wait 相同 for(;) /使用循环不断检测子进程是否结束 pid=waitpid(-1,NULL,WNOHANG);if(-1=pid) perror(waitpid);return -1;else if(0=pid) /所有的子进程都在运行状态,做其他处理 printf(主进程空闲处理n);else /所有的子进程都已经结束,退出循环printf(主进程:子进程已经终止n);break;printf(主进程:分析数据n);return 0;1.5创建新的进程exec函数:创建的新的进程的 PID调用函数相同。功能:创建一个新的进程,取代调用进程。格式: #incl
13、ude int execl(const char *path, const char *arg, .);/l 表示可变长参数表注意:第一个参数:要启动程序的路径;第二个参数:程序或命令名称,放在 argv0中;变长参数:程序或命令的选项,放在argv1argvi,i 代表选项的个数中;后面必须以NULL 结束,例如:exec (bin/lsls -l , NULL ),其中 path=bin/ls,arg0= Is ,arg1= -l;至少有一个;返回值:成功则无法返回(因为 exec调用会以跳转到新进程的入口地址为调用进程的结束,而刚刚 运行的代码是不会存在于新进程的地址空间中的),失败返回
14、-1 ,并设置errno ;功能:创建一个新的进程,取代调用进程。格式: #include int execlp(const char *file, const char *arg, .);/p 表示自动搜索 PATH 路径注意:第一个参数:要启动程序的名字;系统会根据path和名字的拼接自动去找;第二个参数:程序或命令名称,放在 argv0中;变长参数:程序或命令的选项,放在argv1argvi,i代表选项的个数中;后面必须以NULL结束,例如:exec (ls ls -l , NULL ),其中 path=bin/ls,arg0= ls ,arg1= -l;返回值:成功则无法返回,失败返回
15、-1 ,并设置errno ;功能:创建一个新的进程,取代调用进程。格式: #include int execle(const char *path, const char *arg,., char * const envp);/e 表示带环境变量注意:与fork和vfork函数不同,exex函数不是创建调用进程的子进程,而是创建一个新的进程取代调用进程。新的进程用自己的全部地址空间,覆盖调用进程的地址空间,进程PID保持不变。返回值:成功则无法返回,失败返回-1 ,并设置errno ;int execv(const char *path, char *const argv); /v 表示字符指
16、针数组int execvp(const char *file, char *const argv);int execve(const char *path, char *const argv口,char *const envp);类似前面三个函数,只是将命令行参数直接放到了argv口数组中;*实验程序:打印命令行参数和环境变量,生成 argenv程序,供后面使用*#include#include/打印命令行参数void printArgv(char*argv口)printf(- 命令参数n);while(argv&*argv)printf(%sn,*argv+);printf(n);打印环境变
17、量void printEnvp(char*envp口)printf( 环境变量n);while(envp&*envp)printf(%sn,*envp+);printf(n); int main(int argc,char*argv,char*envp口)printArgv(argv);printEnvp(envp);return 0;*使用exec函数家族创建新进程argenv*#include#includeint main()printf(创建一个新进程n); 可以打印出来/创建目标进程argenv/*i (1) nt res=execl(./argenv,argenv,hello,wo
18、rld,hello world,NULL); if(-1=res)perror(execl);return -1;*/* (2) /定义字符指针数组来存放命令行参数char*argv=argenv,hello,world,hello world,NULL;启动 argenv 进程int res=execv(./argenv,argv);if(-1=res)perror(execv);return -1;*/* (3) /定义字符指针数组存放环境变量char*envp=NAME=NARUKANA,AGE=17500”,NULL;/创建新进程argenvint res=execle(./argen
19、v,argenv,hello,world,hello world,NULL,envp); if(-1=res)perror(execle);return -1;*/* (4) /定义字符指针数组来存放命令行参数char*argv=argenv,hello,world,hello world,NULL;/定义字符指针数组存放环境变量char*envp=NAME=NARUKANA,AGE=17500”,NULL;int res=execve(./argenv,argv,envp);if(-1=res)perror(execve);return -1;*/* (5) int res=execlp(a
20、rgenv,argenv,hello,world,hello world,NULL); if(-1=res)perror(execlp);return -1;*/ (6)定义字符指针数组来存放命令行参数char*argv=argenv,hello,world,hello world,NULL;int res=execvp(argenv,argv);if(-1=res) perror(execvp);return -1;printf(创建新进程成功n); 若argenv进程创建成功,则无法打印/因为原来的进程已经被新创建的argenv进程取代return 0;其实只有execve是真正的内核函数
21、,其他五个exec函数只不过是对该函数简单包装。1.6 调用exec函数不仅改变调用进程的地址空间和进程映像,调用进程的属性也会发生变化:(1)任何出于 阻塞状态的信号都会丢失;(2)被设置为 捕获的信号 会还原为默认操作;(3)有关线程的设置都会还原到缺省值(复位) ;(4)有关进程的 统计信息也会复位(如进程消耗的时间等);(5)与原进程内存相关的任何数据都会丢失,包括内存映射文件;(6)标准库在用户空间维护的一切数据结构,如 atexit或on_exit函数注册的退出处理函数,都会丢失;但是也有属性会被新进程继承下来,如 PID,PPID,实际用户ID,实际组ID,优先级,以及文件描述符
22、表(即用原来进程创建的文件描述符在现在的新进程中也能直接使用)。1.7 调用exec函数固然可以创建出新的进程,但是新的进程会取代原来的进程。如果既希望创建新的进程,同时又希望原来的进程继续存在,则可以采用fork+exec 模式,即在fork产生的子进程中调用exec函数,新进程取代了子进程,但父进程依然存在。如:pid_t pid=fork (); 创建子进程if(-1=pid). .if(0=pid)int res=execl( /bin/ls , ls , -l ,NULL);/ 在子进程中创建新进程 if(-1=res). .1.8 system 函数使用时引入头文件stdlib.h功能:创建command 参数指定的进程并返回命令所创建的进程的终止状态。格式:#include int system(const char *command);注意:一个参数:shell命令行字符串,可以为 NULL,此时表示检测当前shell是否可用;返回值:成功返回command 进程的终止状态,失败返回-1 ,并设置errno 。* 使用 system创建新进程 *#include#include#include#include int main()int status=system(NULL);if(-1=st
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 工程石材购销合同模板
- 原油供货合同范例
- 工厂杂工 合同范例
- 工程电子采购合同范例
- 委托推广app合同范例
- 天猫建材合同范例
- 合同模板模板官方
- f住房借款合同范例
- 合作建房拍卖合同范例
- 园林补植合同模板
- GB/T 25356-2024机场道面除冰防冰液
- 18 《浏览数字博物馆》(教学设计) 五年级信息技术武汉版
- 期中测试卷(1-4单元)试题-2024-2025学年人教版数学六年级上册
- 建筑工程项目中的精益建造和可持续发展
- 大国三农II-农业科技版智慧树知到期末考试答案章节答案2024年中国农业大学
- (新版)网约配送员职业技能竞赛理论考试题库500题(含答案)
- 绿化养护服务投标方案(技术标)
- 高考生物选择性必修1稳态与调节基础知识填空默写(每天打卡)
- 专题12 应用文写作-【中职专用】备战2025年对口高考语文题型专练 (解析版)
- 代孕合同范本
- 供暖管道改造工程施工方案
评论
0/150
提交评论