进程的创建及相关api,函数的简介和用法

1.1 fork() 函数的效率

       平时来说, 我们编辑1个常见的c程序, 运转这一个程序直到程序甘休,
系统只会分配1个pid给那一个顺序, 也就就说,
系统里只会有一条关于这些顺序的进度.

 

        不过进行了fork() 那个函数就区别了. 

        fork 那个斯洛伐克语单词在保加利亚语里是”分叉”意思,  fork()
这几个函数功用也很切合那么些意思. 
它的功用是复制当前经过(蕴含进程在内部存款和储蓄器里的库房数据)为1个新的镜像.
然后这么些新的镜像和旧的长河相同的时候进行下去. 约等于自然1个进程, 境遇fork()
函数后就分割成多个经过同期实施了. 并且那五个进程是互不影响

 

        参照他事他说加以考察下边这一个小程序:

 

[cpp] view
plain copy

 

  1. int fork_3(){  
  2.     printf(“it’s the main process step 1!!nn”);  
  3.   
  4.     fork();  
  5.   
  6.     printf(“step2 after fork() !!nn”);  
  7.   
  8.     int i; scanf(“%d”,&i);   //prevent exiting  
  9.     return 0;  
  10. }  

 

          在这几个函数里, 共有两条printf语句,
不过执行实践时则打出了3行新闻. 如下图: 

 

图片 1

 

            为啥吗, 因为fork()函数将这么些程序分叉了呀,  见上边包车型客车图解:

图片 2

 

         能够看看程序在fork()函数实行时都唯有1条主进度, 所以 step 1
会被打字与印刷输出1次.

         试行 fork()函数后,  程序分叉成为了八个过程, 1个是原本的主进度, 
另1个是新的子进度, 它们都会实施fork() 函数前面包车型客车代码, 所以 step2 会被
两条长河分别打字与印刷输出各贰次, 荧屏上就合计3条printf 语句了!

 

         能够见到那么些函数最终边作者用了 scanf()函数来严防程序退出, 
这时查看系统的进程, 就能够发掘八个一样名字的进程:

 

{

4. 利用 fwrite() ,fork() 和exec 函数 替代system()函数.

 

     上面讲过了, 就算exec函数不援救管线, 况兼命令参数复杂,
可是它支持实行脚本啊, 所以大家可以使用fwrite将
有管线管理的一声令下写入1个脚本中, 然后使用exec函数来实行这些脚本.

     上边会编写1个base_exec(char *) 函数, 接收1个字符串参数,  
然后举办它.

 

      这里只会大要写出这一个函数的逻辑步骤:

      1. 行使getuid函数获得当前的pid,  然后利用pid获得当前独一的文书名,
幸免因为同一程序同一时候进行产生冲突!

      2.  选取fwrite函数在 /tmp/上边  创设1个方面文件名的本子文件.    
因为/tmp/ 任何客户都足以读写啊

     3.  把命令参数写入脚本

     4. 应用fork() 和 exec() 推行这么些本子

     5. 有需求的话当exec施行完, 记录日志.

 

     下边正是i代码:

头文件:

base_exec.h

 

[cpp] view
plain copy

 

  1. #ifndef __BASE_EXEC_H_  
  2. #define __BASE_EXEC_H_  
  3.   
  4.     int base_exec(char *) ;  
  5.   
  6. #endif /* BASE_EXEC_H_ */  

源文件:

 

base_exec.c

 

[cpp] view
plain copy

 

  1. #include “base_exec.h”  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #include <unistd.h>  
  6. #include <time.h>  
  7.   
  8. #define LOGFILE “/home/gateman/logs/c_exec.log”  
  9.   
  10. int base_exec(char * pcmd){  
  11.     FILE * pf;  
  12.     pid_t pid = getpid();  
  13.     char pfilename[20];  
  14.     sprintf(pfilename, “/tmp/base_exec%d.sh”,pid);  
  15.   
  16.     pf=fopen(pfilename,”w”); //w is overwrite, a is add  
  17.     if (NULL == pf){  
  18.         printf(“fail to open the file base_exec.sh!!!n”);  
  19.         return -1;  
  20.     }  
  21.   
  22.     fwrite(“#!/bin/bashn”, 12, 1, pf);  
  23.     fwrite(pcmd, strlen(pcmd),1, pf);  
  24.     fwrite(“n”, 1,1, pf);  
  25.   
  26.     fclose(pf);  
  27.   
  28.     if (fork() ==0 ){  
  29.         //child processj  
  30.         char * execv_str[] = {“bash”, pfilename, NULL};  
  31.         if (execv(“/bin/bash”,execv_str) < 0){  
  32.             perror(“fail to execv”);  
  33.             exit(-1);  
  34.         }  
  35.     }else{  
  36.         //current process  
  37.         wait();  
  38.         pf=fopen(LOGFILE,”a”);  
  39.   
  40.         if (NULL == pf){  
  41.             printf(“fail to open the logfile !!!n”);  
  42.             return -1;  
  43.         }  
  44.         time_t t;  
  45.         struct tm * ptm;  
  46.         time(&t);  
  47.         ptm  = gmtime(&t);  
  48.         char cstr[24];  
  49.         sprintf (cstr, “time: %4d-%02d-%02d %02d:%02d:%02dn”, 1900+ptm->tm_year,ptm->tm_mon,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);  
  50.         fwrite(cstr, strlen(cstr),1, pf);  
  51.   
  52.         int uid = getuid();  
  53.         sprintf(cstr, “uid: %dncommand:n”,uid);  
  54.         fwrite(cstr, strlen(cstr),1, pf);  
  55.   
  56.         fwrite(pcmd, strlen(pcmd),1, pf);  
  57.         fwrite(“nnn”, 3,1, pf);  
  58.         fclose(pf);  
  59.         remove(pfilename);  
  60.         return 0;  
  61.     }  
  62.     return 0;  
  63. }  

printf(“child var value not changen:”);

1. fork() 函数

(1)符合规律终止:

2.6 execle 函数

 

[cpp] view
plain copy

 

  1. if (fork() == 0){  
  2.     //child process  
  3.     char * env[] = {“PATH=/home/gateman”, “USER=lei”, “STATUS=testing”, NULL};  
  4.     if (execle(“/usr/bin/env”,”env”,NULL,env) <0){  
  5.         perror(“error on exec”);  
  6.         exit(0);  
  7.     }  
  8. }else{  
  9.     //parent process  
  10.     wait(&childpid);  
  11.     printf(“execle donenn”);  
  12. }  

 

 

 输出:

图片 3

 

 

//_exit(0)   exit(0)  return 0

3. fork() 和exec 函数与system()函数相比

     见到上边execvp函数的输出. 你会发觉 exec函数只是系统调用,
它是不帮忙管线管理的

     而system()函数是永葆的.   他的此中会自动fork()
1个子进度,但是成效未有fork() 和 exec协作使用好.

 

     但是exec 帮助施行脚本. 
所以不要求管线管理的通令或许脚本可以动用fork() 和 exec函数来试行.

 

 

if(getenv(“B”) == NULL)

2.3 execve 函数

 

[cpp] view
plain copy

 

  1. if (fork() == 0){  
  2.     //child process  
  3.     char * execve_str[] = {“env”,NULL};  
  4.     char * env[] = {“PATH=/tmp”, “USER=lei”, “STATUS=testing”, NULL};  
  5.     if (execve(“/usr/bin/env”,execve_str,env) <0 ){  
  6.         perror(“error on exec”);  
  7.         exit(0);  
  8.     }  
  9. }else{  
  10.     //parent process  
  11.     wait(&childpid);  
  12.     printf(“execve donenn”);  
  13. }  

 

 

{

2. exec 函数组

 

      须要小心的是exec并非1个函数, 其实它只是一组函数的统称,
它富含上面6个函数:

     

[cpp] view
plain copy

 

  1. #include <unistd.h>  
  2.   
  3. int execl(const char *path, const char *arg, …);  
  4.   
  5. int execlp(const char *file, const char *arg, …);  
  6.   
  7. int execle(const char *path, const char *arg, …, char *const envp[]);  
  8.   
  9. int execv(const char *path, char *const argv[]);  
  10.   
  11. int execvp(const char *file, char *const argv[]);  
  12.   
  13. int execve(const char *path, char *const argv[], char *const envp[]);  

 

       能够看看那6个函数名字区别, 何况他们用于接受的参数也不一致.

       实际上他们的效果与利益都是大概的,
因为要用以接受不一样的参数所以要用差别的名字分别它们,
终究c语言未有函数重载的机能嘛..  

 

       不过实际上它们的命名是有规律的:

       exec[l or v][p][e]

       exec函数里的参数能够分成3个部分,      施行文书部分,    
命令参数部分,   情形变量部分.

        譬喻我要实施1个指令   ls -l /home/gateman  

        试行文书部分就是  “/usr/bin/ls”

        命令参加比赛部分正是 “ls”,”-l”,”/home/gateman”,NULL             
见到是以ls开头 每1个空格都不能不分别成2个部分, 并且以NULL结尾的啊.

        碰到变量部分, 这是1个数组,最终的成分必得是NULL 譬如  char *
env[] = {“PATH=/home/gateman”, “USER=lei”, “STATUS=testing”, NULL};

        

        好了说下命名法规:

        e后续,  参数必得带景况变量部分,  
情况变零部分参数会成为施行exec函数时期的情状变量, 少之甚少用

        l 后续,   命令参数部分必需以”,” 相隔, 最终1个指令参数必需是NULL

        v 后续,  
命令参数部分必需是1个以NULL结尾的字符串指针数组的底部指针.        
譬喻char * pstr正是1个字符串的指针, char * pstr[] 正是数组了,
分别指向各样字符串.

        p后续,   推行文书部分能够不带路径, exec函数会在$PATH中找

 

          

         还或然有1个注意的是, exec函数会代替实施它的历程,  也正是说,
一旦exec函数实行成功, 它就不会回到了, 进度停止.  
不过假如exec函数实践停业, 它会再次来到失利的音信, 
而且经过继续实践前边的代码!

 

       平常exec会放在fork() 函数的子进程部分, 来代替子进程实践啦,
实践成功后子程序就能够藏形匿影,  不过实践停业以来,
必需用exit()函数来让子进程退出!

       上面是逐条例子:

 

 

2.4 execl 函数

 

[cpp] view
plain copy

 

  1. if (fork() == 0){  
  2.     //child process  
  3.     if (execl(“/usr/bin/echo”,”echo”,”executed by execl” ,NULL) <0 ){  
  4.         perror(“error on exec”);  
  5.         exit(0);  
  6.     }  
  7. }else{  
  8.     //parent process  
  9.     wait(&childpid);  
  10.     printf(“execv donenn”);  
  11. }  

 

运作结果如下:

2.5 execlp 函数

 

[cpp] view
plain copy

 

  1. if (fork() == 0){  
  2.     //child process  
  3.     if (execlp(“echo”,”echo”,”executed by execlp” ,NULL) <0 ){  
  4.         perror(“error on exec”);  
  5.         exit(0);  
  6.     }  
  7. }else{  
  8.     //parent process  
  9.     wait(&childpid);  
  10.     printf(“execlp donenn”);  
  11. }  

 

 

 

如上图, pid 8808 那个正是主进度了, 而 pid  8809卓殊便是子进度啊,
因为它的parent pid是 8808啊!

          

          亟需小心的是, 倘若没有做特别管理, 子进度会一直留存,
固然fork_3()函数被调用完毕,  子进度会和主程序一样,重回调用fork_3()
函数的上拔尖函数继续实施, 直到全体程序退出.

 

          可以看出, 若是fork_3() 被实行2次,  主程序就能够分开五回,
最终产生4个经过, 是还是不是有一些危急. 所以上面所谓的出格管理很关键呀!

 

 

1.2 差距分主程序和子程序.

        实际采取中, 单纯让程序分叉意义相当的小, 我们新扩张一个子前后相继,
很恐怕是为了让子进度单独实践一段代码. 达成与主进程分裂的功效.

         要兑现地点所说的效能,
实际上就是让子进度和主进程推行不一的代码啊.

         所以fork() 实际上有重回值, 何况在两条经过中的重临值是见仁见智的,
在主进程里 fork()函数会回到主进度的pid,   而在子进度里会再次来到0!  
所以大家得以依赖fork() 的返回值来判断进程到底是哪位进度, 就足以行使if
语句来进行不一致的代码了!

 

        如上边这几个小程序fork_1():

 

[cpp] view
plain copy

 

  1. int fork_1(){  
  2.     int childpid;  
  3.     int i;  
  4.   
  5.     if (fork() == 0){  
  6.         //child process  
  7.         for (i=1; i<=8; i++){  
  8.             printf(“This is child processn”);  
  9.         }  
  10.     }else{  
  11.         //parent process  
  12.         for(i=1; i<=8; i++){  
  13.             printf(“This is parent processn”);  
  14.         }  
  15.     }  
  16.   
  17.     printf(“step2 after fork() !!nn”);  
  18. }  

        作者对fork() 函数的再次回到值举行了推断, 假诺 重临值是0,
小编就让认为它是子进程, 不然是主程序. 
那么作者就足以让这两条经过输出区别的新闻了.

 

       

          输出新闻如下图:

图片 4

 

          能够看来 子程序和主程序分别出口了8条分裂的新闻, 
不过它们而不是平整交替输出的, 因为它们两条经过是相互平行影响的,
哪个人的手快就在显示器上先输出,  每便运转的结果都有不小或许分歧哦.

 

        上面是图解:

图片 5

 

          由图解知两条经过都对fork()重临值实施决断,  在if
决断语句中分别实行各自的代码.  不过if判断达成后, 
依旧会回各自推行接下去的代码. 所以 step2 恐怕输出了2次.

输入字符后:

2.1  execv 函数

 

[cpp] view
plain copy

 

  1. int childpid;  
  2. int i;  
  3.   
  4. if (fork() == 0){  
  5.     //child process  
  6.     char * execv_str[] = {“echo”, “executed by execv”,NULL};  
  7.     if (execv(“/usr/bin/echo”,execv_str) <0 ){  
  8.         perror(“error on exec”);  
  9.         exit(0);  
  10.     }  
  11. }else{  
  12.     //parent process  
  13.     wait(&childpid);  
  14.     printf(“execv donenn”);  
  15. }  

留心字符串指针数组的概念和赋值

 

 

{

1.4 使用wait() 函数主程序等子程序施行完毕(退出)后再推行.   

 

        由地点例子得到消息,  主程序和子程序的实践顺序是自由的, 
然而实际境况下, 日常大家希望子进程推行后,  才继续执行主进度. 

        比如对于地点的fork_1()函数, 笔者想先输出子进度的8个 “This is
child process”  然后再出口 8个 主进度”This is parent process”, 改肿么办?

        wait()函数就提供了这么些意义,    在if 条件内的  主进度呢部分内
加上wait() 函数, 就可以让主进程实行fork()函数时先hold 住,
等子进程退出后再进行, 经常会同盟子进度的exit()函数一起使用.

 

        我将fork_1()函数修改一下, 增多了wait()语句:

 

[cpp] view
plain copy

 

  1. int fork_1(){  
  2.     int childpid;  
  3.     int i;  
  4.   
  5.     if (fork() == 0){  
  6.         //child process  
  7.         for (i=1; i<=8; i++){  
  8.             printf(“This is child processn”);  
  9.         }  
  10.         exit(0);  
  11.     }else{  
  12.         //parent process  
  13.         wait();  
  14.         for(i=1; i<=8; i++){  
  15.             printf(“This is parent processn”);  
  16.         }  
  17.     }  
  18.   
  19.     printf(“step2 after fork() !!nn”);  
  20. }  

 

输出:

 

图片 6

      看到那时的显示器输出就很有规律了!

      其实wait() 函数还应该有1个效果与利益, 正是足以收到1个
pid_t(在unistd.h内,其实便是Int啦) 指针类型参数,  
给这一个参数赋上子进度退出前的系统pid值

     流程图:

  图片 7

 

 

 

 

   从下面能够看来,根据copy-on-write的商讨,在子进度中,更换父进度的数据时,会先
复制父进程的数据修然后再改,进而达到子进度对数据的退换不影响父进度。可是大家发现,复制的前后,其值的地点都是一律的。为啥呢?子进度拷贝的时候也拷贝了父进度的设想内部存储器”页”,那样他们的虚构地址都同一,可是对应区别的情理内存空间。

2.2  execvp 函数

 

 

[cpp] view
plain copy

 

  1. if (fork() == 0){  
  2.     //child process  
  3.     char * execvp_str[] = {“echo”, “executed by execvp”,”>>”, “~/abc.txt”,NULL};  
  4.     if (execvp(“echo”,execvp_str) <0 ){  
  5.         perror(“error on exec”);  
  6.         exit(0);  
  7.     }  
  8. }else{  
  9.     //parent process  
  10.     wait(&childpid);  
  11.     printf(“execvp donenn”);  
  12. }  

 

 

1.4 使用exit() 函数令子进度在if 判定内结束.

          参谋上面包车型大巴函数, 固然使用if 对 fork() 的再次来到值进行判别, 
实现了子进度和 主进度在if判定的界定内实践了差别的代码, 
不过就疑似上边的流程图, 一旦if实施到位, 他们依然会独家实行前面包车型客车代码. 

          日常那不是我们期望的, 
大家愈来愈多时会希望子进度施行一段非常的代码后就让他停止, 
后边的代码让主程序试行就行了.

          那个实现起来相当粗略, 在子程序的if 条件内最终加上exit()
函数就ok了.

 

         将方面包车型客车fork_1()函数修改一下, 加上exit语句:

 

[cpp] view
plain copy

 

  1. int fork_1(){  
  2.     int childpid;  
  3.     int i;  
  4.   
  5.     if (fork() == 0){  
  6.         //child process  
  7.         for (i=1; i<=8; i++){  
  8.             printf(“This is child processn”);  
  9.         }  
  10.         exit(0);  
  11.     }else{  
  12.         //parent process  
  13.         for(i=1; i<=8; i++){  
  14.             printf(“This is parent processn”);  
  15.         }  
  16.     }  
  17.   
  18.     printf(“step2 after fork() !!nn”);  
  19. }  

       再看看输出:

 

图片 8

 

            能够看出, step2只输出1次了,   那是因为子程序在
if条件内终止了哟, 一旦 if 剖断成, 就只剩余1个主进度推行上边包车型大巴代码了,
那多亏大家想要的!

            注意: exit() 函数在 stdlib.h 头文件内

 

流程图:

图片 9

 

 

 

exit(-1);

linux c语言 fork() 和 exec 函数的简要介绍和用法

 

      若是大家在编写制定1个c程序时想调用1个shell脚本大概推行1段 bash
shell命令, 应该怎么兑现吗?

      其实在<stdlib.h>
那些头文件中含有了1个调用shell命令或许脚本的函数 system();直接把
shell命令作为参数字传送入 system函数就可以了, 的确很方便. 关于system
有一段那样的牵线:   system 试行时内部会活动启用fork() 新建1个进度, 
功能没有一贯动用fork() 和 exec函数高.

 

       那么这篇文章其实就是介绍一下fork() 和 exec函数的用法,
以至哪些行使它们来取代system函数.

      

return
-1;

}else
if(WIFSIGNALED(status)){

int main(int argc,char *argv[])

图片 10

printf(“env
C = %s.n”,getenv(“C”));

图片 11

#include <unistd.h>

WUNTRACED,若某完成帮助作业调控,则由pid钦点的任一子进度情形已暂停,且其场地自暂停以来还没告知过,则赶回其意况。

只顾:父进度调用while(waitpid(-1,&status,WUNTRACED)   != -1 )

#include <stdio.h>

 

   
vfork和fork之间的另五个分别是:vfork保险子进度先运营,在它调用exec或exit之后
父进度才可能被调整运维。(假使在调用那五个函数以前子进程依赖于父进度的越发动作,则会导致死锁)

图片 12

#include <sys/waith.h>

实例1:

 

#include <stdlib.h>

0:同wait,阻塞父进度,等待子进度退出。

{

printf(“start to execle.n”);

}

execl(“./B”,”B”,”1″,”2″,”3″,NULL);

printf(“&glob = %pn”,&glob);

#include <stdio.h>

 

return
0;

 

printf(“child process : %d calling exit(7).n”,getpid());

 

 

图片 13

}

{

编写翻译运转结果:

 

printf(“child process %d is exit by signal,the signal num is
%d.n”,pid,WTERMSIG(status));

给进程15494发个复信号

{

 

#include <stdio.h>

}else 

 

#include <stdlib.h>

printf(“Father wait zombie now – pid : %d.n”,getpid());

if((pid =
fork()) < 0)

printf(“&glob = %pn”,&glob);

{

exit(0);

if((pid =
fork()) < 0)

while(1);

       
2.从地点能够看出四遍的周转结果不等同。大家知晓write函数是不带缓存的。因为在fork在此以前调用write,所以其数额写到规范输出贰回。然则,规范I/O库是带缓存的。如若标准输出连到终端设备,则它是行缓存的,不然它是全缓存的。当以交互情势运行该程序时,只获得printf输出的行壹回,其原因是标准输出缓存由新行符刷新。不过当将行业内部输出重新定向到三个文件时,却获得printf输出游四次。其原因是,在fork以前调用了printf一遍,当调用fork时,该行数据仍在缓存中,然后在父进度数据空间复制到子进度中时,该缓存数据也被复制到子进度中。于是当场父、子进度各自有了带该行内容的缓存。在exit此前的第3个printf将其数额拉长到现有的缓存中。当每一种进度终止时,其缓存中的内容被写到相应文件中。

图片 14

案例研究三、

#include <stdio.h>

#include <unistd.h>

{

}

perror(“Fail
to fork”);

#include <errno.h>

#include <stdlib.h>

printf(“__________________________________n”);

 

pid_t  wait(int  *status);

 

}

 

printf(“child process in proces group %d.n”,getpgid(0));

 

{

wait函数:调用该函数使进度阻塞,直到任三个子经过结束大概是该进程接收到三个实信号截止。假设该进度未有子进度恐怕其子进度已经竣事,wait函数会立即回去。

 

就算某些进度想同期实行另一个前后相继,它就足以调用fork函数创造子进度,然后在子进度中调用任何叁个exec函数。那样看起来就类似通过奉行应用程序而爆发了八个新进度同样。

 

 

{

图片 15
图片 16

运维结果:

 

return
-1;

}

参数表传递方式

printf(“Father exiting now – pid : %d.n”,getpid());

if
(execv(“/bin/ps” ,arg) < 0)

int glob = 6;

}

程序运转结果:

}

exit(0);

int
status;

}

调用出错:-1

{

}

图片 17

{

if(write(STDOUT_FILENO,buf,sizeof(buf) -1) != sizeof(buf)
-1)

perror(“Fail
 to fork”);

perror(“execl”);

int
pid;

 

}

}

#include <stdio.h>

 

 

图片 18

{

 

 

exit(-1);

 

exit(0);

if(getenv(“PATH”) == NULL)

#include <stdio.h>

 

printf(“child exiting now – pid : %d.n”,getpid());

printf(“All
child process is exit,father is exit.n”);

参数:

printf(“child runing now – pid : %d.n”,getpid());

}

exec函数族提供了一种在进程中运行另贰个程序实践的措施。它能够凭借钦命的文件名或目录名找到可试行文件,并用它来代替原调用经过的数据段、代码段、和酒店段。在试行完事后,原调用经过的源委除了进程号外,其余一切都被轮换了。

}else{

exit(-1);

}else{

图片 19

 

动用的界别

}else{

鉴于父进度调用waitpid等待子进度15784脱离,此时这一个进度还没退出,看能够看见父进程处于可间歇的睡觉情况。

exit(0);

{

图片 20

图片 21

}else{

printf(“create child process : %d.n”,getpid());

}else if(pid
== 0){

int glob = 6;

运作结果:

exec函数族能够暗中同意使用系统的蒙受变量,也能够流传内定的情状变量。这里,以”e”(Envirment)结尾的三个函数execle、execve就能够在envp[]中传递当前历程所接纳的处境变量。

 

 

 

 

if((pid =
fork()) < 0)

图片 22

可试行文件查找方法

#include <stdlib.h>

{

#include <stdlib.h>

}

四、exec函数族

#include <unistd.h>

探究2.exit()

perror(“Fail
to fork”);

从地点我们看看,test.txt的从头到尾的经过为空.为何吗?因为标准I/O函数是带缓存的,举行fputs的时候是先向缓存中写的,独有当缓存满的时候才会刷新的缓冲区的。从上述大家开掘,当进程退出时,试行_exit()函数并不曾刷新缓冲区的数目,而是平昔终止进度的。

 

printf(“Not
know.n”);

        

从地点大家能够见见,当exit()函数结束进度的时候,对缓存进行了管理,把缓存的数量写到了磁盘文件中。

#include <string.h>

实例 2:

}

printf(“child process : %d calling exit(6).n”,getpid());

 

探究3.return

 

#include <stdio.h>

return
0;

int
status;

动用采纳WNOHANG且并未子进度结束时:0

{

图片 23

2.A进度打印”child process %d exit”,调用exit(2),甘休

#include <stdlib.h>

printf(“Father exit now – pid : %d.n”,getpid());

printf(“create child process : %d.n”,getpid());

 

}else if(pid
== 0){

sleep(2);

}else{

{

if((pid =
fork()) < 0 ){

图片 24

}

printf(“start to execl.n”);

 

}else if(pid
== 0){

 

printf(“fail
to getenv B.n”);

一函数名的第5个字母按来区分,字母”l”(list)的代表一个三个点数形式;字母”v”(vector)的意味将兼具参数构产生指针数组传递,其语法为char
*const argv[]

exit(7);

 

失败:-1

int
var;

printf(“create child process : %d.n”,getpid());

 

}

 

{

waitpid函数:效用和wait函数类似。可以钦命等待有些子进程结束以致等待的主意(阻塞或非阻塞)。

exit(-1);

exit(0);

函数参数:

printf(“All
child process is exit,father is exit.n”);

 

int
pid;

printf(“child var value change:n”);

}else{

if((pid =
fork()) < 0 ){

char *const envp[] = {“B”,”1″,”2″,”3″,NULL}

}else{

}

 

printf(“before forkn”);

getchar();

exit(7);

printf(“child process %d is exit by signal,the signal num is
%d.n”,pid,WTERMSIG(status));

#include <sys/wait.h>

#include <stdlib.h>

glob
++;

{

return
-1;

 

图片 25

{

程序运维结果:

 

 

while((pid =
waitpid(pid,NULL,WNOHANG)))

    (a)在main函数内进行return语句。那等效于调用exit。

exit和_exit的不同

图片 26

 

perror(“Fail
to fork”);

int
pid;

 

perror(“Fail
to execl”);

 

_exit()函数的效劳最为简练:直接进度结束运营,清除其利用的内部存款和储蓄器空间,并销毁其在基础中的种种数据结构;

 

}else{

 

图片 27

char *
const envp[] = {“B=hello”,NULL};

    

 

#include <stdio.h>

1.在父进度中创立多个子进度(A   B)

因为大家掌握vfork保证子进度先运营,子进度运维结束后,父进度才开首运营。所以,第一遍打字与印刷的是子进度的打字与印刷的音讯,能够看出var值产生了89。子进度甘休后,父进度运维,父进度首先打字与印刷fork调用重回给他pid的值(便是子进度pid)。以上我们能够看看,vfork创造的子进程和父进度运维的地址空间一样(子进程改造了var
值,父进度中的var值也进展了变动)。

 

printf(“create child process : %d.n”,getpid());

 

 

execv(“./B”,envp);

#include <stdio.h>

status是三个整型指针,指向的目的用来保存子进度退出时的状态。

 

好端端:甘休的子进度的长河号

程序运维结果:

 

}

return
-1;

{

 

printf(“&var
= %pn”,&var);

 

printf(“child process : %d calling exit(7).n”,getpid());

}

exit(0);

}

printf(“start to execl.n”);

 

探究 1._exit()

perror(“fail
to write”);

exec.c  调用exec在那之中的二个函数; gcc exec.c -o exec; ./exec

wait(NULL);

while(1);

探究1.vfork()

int
pid;

return
-1;

案例二、利用wait等待回收处于尸鬼态的子进度

子进度的收尾状态可由Linux中一些一定的宏来测定。

while
(1);

}else{

 

 

}

返回值

}else if(pid
== 0){

三种艺术:三个三个列举和将具备参数通过指针数组传递

 

int main(int argc,char *argv[])

perror(“Fail
 to fork”);

//if
(execl(“/bin/ps”, “ps”, “-ef”, NULL) < 0)

B.status若不为空,表示保存子进度退出时的景色

从上述钻探可以预知,每当子进程截止后,wait函数就能够回到哪个子进度甘休的pid。若无子进度存在,wait函数就赶回-1。

}

}else{

注意:

图片 28

 

var
++;

}else{

{

图片 29

int
pid;

 

char buf[] = “a write to
stdoutn”;

 

图片 30

 

var =
88;

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注