Menu

进程创建函数fork,Linux内核学习笔记



后生可畏、 进程创制:

6、调用get_pid(卡塔尔国为新进程获得叁个实用的PID

  1 #include <unistd.h>
  2 #include <stdio.h>
  3 
  4 int main(){
  5     pid_t fpid;
  6     int count= 0;
  7     fpid = fork();              // fpid 为fork()的返回值
  8     if(fpid < 0){               // 当fork()的返回值为负值时,表明调用 fork() 出错
  9         printf("error in fork!");
 10     }
 11     else if(fpid  == 0){        // fork() 返回值为0,表明该进程是子进程
 12         printf("this is a child process, the process id is %d\n",getpid());
 13         count++;
 14     }
 15     else{                       // fork() 返回值大于0,表明该进程是父进程,这时返回值其实是子进程的PID
 16         printf("this is a father process, the process id is %d\n",getpid());
 17         count++;
 18     }
 19     printf("计数 %d 次\n",count);
 20     return 0;                                                                          
 21 }

pid_t fork(void卡塔尔(英语:State of Qatar)//成功再次回到0,退步重临-1

  日常,exec(卡塔尔(英语:State of Qatar) 会放在 fork(卡塔尔(英语:State of Qatar)函数的子进度部分,来替代子进程继续推行,exec(卡塔尔(قطر‎试行成功后子进度就能销声匿迹,可是进行停业以来,就应该要使用 exit(卡塔尔函数来让子进程退出。上边用风华正茂段简单的代码来演示一下 exec(卡塔尔国函数簇中的二个函数的用法,其他的参照:

2、检查新创造的那几个子进度后,当前顾客所用有的经过数目未有当先给他分配的财富的限量

·  当 exec(卡塔尔(قطر‎ 履行成功时,exec(卡塔尔国函数会替代施行它的经过,当时,exec(卡塔尔国 函数未有再次回到值,进度甘休。当 exec(卡塔尔函数施行停业时,将重临退步新闻(再次回到-1),进度继续实施前边的代码。

在Linux中,fork(卡塔尔(قطر‎和vfork(卡塔尔就是用来制造进度的四个函数,他们的相关新闻如下:

 

二、达成进度和界别

  在Linux系统中,通过调用fork(卡塔尔国来成立一个经过。调用 fork(卡塔尔(英语:State of Qatar)的长河称为父进度,新产生的进度称为子进程。在该调用甘休时,在重返点那个相似的位子上,父进度苏醒实施,子进程始起实施。fork(卡塔尔国系统调用从水源重回两回:二回回到到父进程,另二遍回到到新发生的子进程。使用fork(卡塔尔创立新历程的流程如下:

sys_vfork(struct pt_regs *regs)
{
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
regs->gr[30], regs, 0, NULL, NULL);
}

 

始建进度函数:

8)调用 schedule(卡塔尔(قطر‎ 切换来新的历程,继续试行。由于 EXIT_ZOMBIE
状态的进程不会被再调度,所以那是进程所施行的尾声风流倜傥段代码, do_exit()未有重返值。

1、Linux是通过_cloen(卡塔尔(英语:State of Qatar)系统调用来完毕fork(卡塔尔的,那风姿浪漫调用经过风流倜傥雨后玉兰片的参数标识来指明父子进度需求的能源。Fork(卡塔尔(英语:State of Qatar),vfork(卡塔尔国,_cloen(卡塔尔(قطر‎库函数都依据各自供给的参数标识去调用cloen(卡塔尔国,然后由cloen(卡塔尔去调用do_fork()函数,do_fork(卡塔尔(قطر‎函数也正是的确的创始进程的函数。他做到了创立进程的绝大比非常多干活。同期她还有或然会调用copy_process(卡塔尔(قطر‎函数。然后让进程起头运维。

5)调用 exit_files() 和
exit_fs(卡塔尔,以独家依次减少文件描述符、文件系统数据的援用计数,若里面某些引用计数的值降低到零,则意味着从未经过使用相应的财富,能够自由掉进度占用的公文描述符、文件系统财富;

9、最后,copy_proccess(卡塔尔国做截至工作并回到一个只想子进度的指针。

  9)调用 alloc_pid(卡塔尔国 为新历程分配三个使得的 PID;

连带函数:fork, execle, execlp, execv, execve, execvp
表头文件:#include 
函数定义:int execl(const char *path, const char *arg, …);
函数表达:execl(卡塔尔(قطر‎用来实践参数path字符串所代表的公文路线,
接下来的参数代表试行该文件时传递的argv[0],argv[1]…..是后一个参数必得用空指针NULL作了结
回来值   :成功则不重回值, 失败重回-1, 失败原因存于errno中
错误代码:参execve(卡塔尔
范例:

3)调用 exit_mm(卡塔尔 函数释放进程占用的
mm_struct,若无别的进程使用它们(地址空间被分享),就到底释放它们;

vfork(卡塔尔函数和fork(卡塔尔(قطر‎函数相比附近,都用于创设子进程。只是其用来创立新的长河,父亲和儿子进度共享虚构内部存款和储蓄器空间。然则在根本中,vfork(卡塔尔国的兑现任然调用fork(卡塔尔函数,调用函数如下:

 

 

  7)将子进度的境况设置为 TASK_UNINTE福特ExplorerRUPTIBLE,保障它不会投运;

2、条用exec函数族更改成立的历程。使用fork(卡塔尔成立出来的长河是前段时间历程的一心复制,但是我们创设进度是为着让新的进程去实行新的主次,由此,就须求用到exec函数族对创造出来的新进程张开改换,让他有所和父进度不等同的事物,改正后就能够实行新的顺序,当然,更正后的子进程包蕴了要执行顺序的信息。

  1)fork() 调用clone;

4、接下去,子进度的图景被安装为不可终端等待情形以确定保障她不会投入运作

  4)调用 dup_task_struct(卡塔尔为新历程创制二个内核栈、thread_info结构和task_struct,那几个值与当下历程的值相近;

3、未来,子进度初步使和睦与父进度不相同开来,进度描述符内的浩大分子都要被清0或然安装开首值。进度描述符的成员值并不是延续而来的,而首即使总结新闻,进度描述符中的大部数额都以分享的。

  上面用大器晚成段轻便的代码演示一下 fork(卡塔尔国 函数:

 

 

 

图片 1

5、copy_process()调用copy_flags()以更新task_struct的flags成员。申明进度是装有最好顾客权限的PF_SUPER[GL450IV标识被清0。注脚进程还没曾调用exec(卡塔尔国函数的PE_FOHavalKNOEXEC标记被设置。

a)在父进度中,fork(卡塔尔(英语:State of Qatar) 再次来到新创建子进度的 PID;

 

  系统经过调用 release_task(卡塔尔 来刑满释放解除劳教进程描述符。

7、依据传给cloen(卡塔尔国的参数标记copy_process(卡塔尔(英语:State of Qatar)拷贝恐怕分享展开的文本、文件系统信、复信号管理函数、进度地址空间和命名空间等。

  3)do_fork() 调用 copy_process() 函数,copy_process(卡塔尔 函数将达成第
4-11 步;

pid_t vfork(void卡塔尔国//成功再次来到0,失败再次来到-1

6)把 task_struct 的 exit_code 成员设置为经过的重返值;

三、在进度窗制程中copy_process(卡塔尔(英语:State of Qatar)函数完毕的干活//摘自:Linux内核设计与完结

10)遵照传递给clone(卡塔尔(قطر‎ 的参数标记,copy_process(卡塔尔(قطر‎拷贝或分享张开的文书、文件系统新闻、时域信号管理函数、进程地址空间和命名空间等;

 

  1 #include <unistd.h>
  2 #include <stdio.h>
  3 #include <errno.h>
  4 #include <string.h>
  5 
  6 int main(){
  7     int childpid;
  8     pid_t fpid;
  9     fpid = fork();
 10     if(fpid == 0){                          // 子进程
 11         char *execv_str[] = {"ps","aux",NULL};      // 指令:ps aux 查看系统中所有进程 
 12         if( execv("/usr/bin/ps",execv_str) < 0 ){
 13             perror("error on exec\n");
 14             exit(0);
 15         }
 16     }
 17     else{
 18         wait(&childpid);
 19         printf("execv done\n");
 20     }
 21 }

在上述函数中,pid_t为隐含类型,实际上正是一个int的品类。隐含类型只数据类型的情理表示是不知所以的仍是不相干的

  exec(卡塔尔(英语:State of Qatar) 并非三个函数,而是二个函数簇,后生可畏共包含三个函数,分别为:
execl、execlp、execle、execv、execvp、execve,定义如下:

  1. [   
  2. /*  执行 /bin/ls  -al  /ect/passwd */  
  3.   
  4. #include <unistd.h>   
  5. /**  
  6. * File: execl.c  
  7. *  
  8. */  
  9. main()   
  10. {   
  11.     execl(“/bin/ls”, “ls”, “-al”, “/etc/passwd”, (char *) 0);
      
  12. }    

11)做一些扫尾工作并回到三个指向子进程的指针。

1、调用dup_task_struct(卡塔尔国为心进度创建二个内核栈、thread_info结构和task_struct,那个值与当下历程的值相符。那个时候,子进程和父进度的汇报符完全雷同。

  注意看最终三个经过,分别是父进程和调用 fork(卡塔尔 后成立的子进度。

2、vfork(卡塔尔和fork(卡塔尔国的机能形似,除了不拷贝父进度的页表项,也正是说不会复制和父进度相关的财富,老爹和儿子进度将分享地址空间,子进程对虚构内存空间的别的实际修改实际上是在退换父进度虚拟内粗空间的剧情。并且其父进度会被梗塞,直到子进度退出或许实施exec(卡塔尔(قطر‎函数族.那样由于父亲和儿子进程分享地址空间,防止了fork在财富复制是的损耗。

7)调用 exit_notify(卡塔尔国 向父进度发送功率信号,并把进程意况设置为
EXIT_ZOMBIE;

fork(卡塔尔国用于创设新的历程,所创办进程为当前经过的子进程,能够因而fork(卡塔尔(英语:State of Qatar)函数的回到质6来支配进度是在父进度中大概在子进程中。尽管运转在父进度中,则赶回PID为子进度的历程号,如若在子进度中,则赶回的PID为0

c)若是 fork(卡塔尔国 调用出错,则赶回负值

风姿浪漫、进度的开创步骤以致开创函数的牵线

4)调用 sem__exit(卡塔尔国 函数,倘使经过排队等候 IPC 非实信号,它则距退出队伍容貌列;

 

1)将task_struct 中的标记成员设置为 PF_EXITING;

3、写时copy机制:Linux系统接纳了“些操作时复制”的方法,其是后生可畏种延迟能源复制的法子,子进程在创立的时候并不复制父进程的连带能源,父亲和儿子进度经过拜候同意气风发的物理内部存储器来伪装已经得以实现了的对能源的复制。这种分享是制度办法是只读格局,那或多或少与vfork是莫衷一是的,当子进度对内存数据存在此些的操作时,才会进香能源的复制。就是出于这种机制的产出,vfork(卡塔尔(英语:State of Qatar)好像已经未有何样意义了。

2)命令参数部分:也正是函数中的 file
部分,该有的建议了参数的传递情势甚至要传送哪些参数。这里,”l”结尾的函数表示使用各类列举的方式传送参数;”v”结尾的代表将全体参数全部构产生一个指针数组进行传递,然后将该数组的首地址当作参数字传送递给它,数组中的最终三个指针供给为
NULL;

8、让父进度和子进程平分剩余的时间片。

图片 2

1、使用fork(卡塔尔(英语:State of Qatar)恐怕vfork(卡塔尔(قطر‎函数成立新的长河

  Unix
下的长河创制很非常,与大多别的操作系统分裂,它分两步操作来成立和施行进程:
fork(卡塔尔 和 exec(卡塔尔(قطر‎ 。首先,fork(卡塔尔(قطر‎通过拷贝当前历程创建四个子历程;然后,exec(卡塔尔国函数肩负读取可推行文件并将其载入地址空间初始运维。

1)奉行文书部分:也便是函数中的 path
部分,该有的提议了可奉行文件的追寻方法。此中execl、execle、execv、execve的物色方法都以选用的相对路线,而
execlp和execvp则能够只交给文件名展开检索,系统会从意况变量
“$PATH”中追寻相应的路径;

1、fork() :kernel/fork.c

 2、exec() :fs/exec.c (源程序
exec.c 达成对二进制可实行文件和 shell 脚本文件的加载与实践)

   在此个程序中,使用 fork(卡塔尔(قطر‎ 成立了二个子历程,随后立时调用 exec(卡塔尔函数簇中的 execv(卡塔尔 函数,execv(卡塔尔(قطر‎函数试行了一条指令,展现当前系统中存有的进程,结果如下(进程有无数,这里只截了黄金年代有的):

#include <unistd.h>  

int execl(const char *path, const char *arg, ...);  
int execlp(const char *file, const char *arg, ...);  
int execle(const char *path, const char *arg, ..., char *const envp[]);  
int execv(const char *path, char *const argv[]);  
int execvp(const char *file, char *const argv[]);  
int execve(const char *path, char *const argv[], char *const envp[]);  

  能够观察,调用 fork()函数后,原来独有三个进度,形成了多少个进度。这四个经过除了 fpid
的值不一样外大约完全相近,它们都继续实行接下去的主次。由于 fpid
的值区别,由此会跻身不一样的剖断语句,那也是怎么五个结实有差别之处的来由。其它,能够观看,父进度的
PID 无独有偶比子进程的 PID 小1。 fork(卡塔尔  的再次回到值有以下两种:

  2)clone() 调用 do_fork();

  那三个函数的效果实在大概,只是接收的参数区别。exec(卡塔尔国函数的参数主要有3个部分:试行文书部分、命令参数部分和意况变量部分:

12)回到 do_fork() 函数,如果 copy_process(卡塔尔函数成功重回,新创制的子进度将被唤起并让其投入运作。

3)意况变量部分:exec(卡塔尔(英语:State of Qatar)函数簇使用了系统暗中认可的境遇变量,也得以流传内定的情状变量。此中 execle
和execve 那八个函数就足以在 envp[] 中内定当前经过所利用的境况变量。

b)在子进度中,fork(卡塔尔 重回0;

 
5)检查并保管新成立那个子进度后,当前客户所怀有的历程数目未有超过给它分配的能源的界定;

二、进度终结

  至此,与经过相关联的富有财富都被放飞掉了,进度不可运维并处于
EXIT_ZOMBIE
退出状态。那时,进度自个儿所占领的内部存款和储蓄器还尚无自由,如内核栈、thread_info
结构和 task_struct
布局等,它存在的含义是向父进程提供音讯,当父进度收到音讯后,也许布告内核那是文不对题的音讯后,进程所具有的剩余的内部存款和储蓄器将被保释。父进度能够经过
wait4(卡塔尔(英语:State of Qatar)系统调用查询子进度是还是不是终止,那其实使得进度具备了等待特定进度推行完结的技术。

出口结果:

2)调用 del_timer_sync(卡塔尔删除任风度翩翩内决停车计时器,以管教未有电火花计时器在排队,也从未反应计时器管理程序在运作;

  进度被成立后,最后要终结。当多个经过终结时,内核必需释放它所占领的能源,并把那意气风发音信告诉其父进度。系统经过
exit(卡塔尔国 系统调用来拍卖终止和抽离进程的相关专业,而超过一半做事则由
do_exit() 来完成 (kernel/exit.c):

 
6)清理子进度经过描述符中的风华正茂对成员(清零或早先化,如PID),以使得子进度与父进度差别开来;

  通常,成立新的进度皆认为着及时执行新的、差别的顺序,而随后调用
exec(卡塔尔(英语:State of Qatar) 那组函数即可创设新的地址空间,并把新的程序载入此中

图片 3

  8)调用 copy_flags() 以更新 task_struct 的 flags 成员;

标签:

发表评论

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

相关文章

网站地图xml地图