美文网首页
linux-08-进程管理2

linux-08-进程管理2

作者: vera姐姐 | 来源:发表于2016-05-12 23:07 被阅读101次

    今天:进程结束 -fork() /exit退出进程/wait()父进程等待子进程/vfork()Unix/Linux 信号

    break是用来退循环,return退函数,exit()退进程

    程序员退出进程的方式:

    1.正常退出

    a.在主函数中执行了return语句(特殊的,因为只对主函数有效)

    b._exit()或_Exit()函数退出进程(立即退出)

    c. exit()退出进行(通用方式)

    d.最后一个线程结束

    2.非正常退出

    a.被信号干掉了,比如:ctrl+cb.最后一个线程被取消

    exit()/_exit()/_Exit()_exit(int) /_EXIT(int)这两个在底层是一样的,_Exit()调用了_exit()

    exit()函数会退出进程,但不一定是马上退出,允许通过atexit()函数注册一些其他的函数,在退出前会先执行注册过的函数。

    _exit()函数会立即退出,退出只做三件事:

    1.关闭文件描述符

    2.让所有的子进程变成孤儿进程

    3.发退出信号给父进程如果没有特殊需求,退出进程用exit()即可。

    wait()和waitpid()

    wait()和waitpid()可以让父进程等待子进程的结束,可以取得子进程结束的方式(正常退出还是非正常退出)和退出码

    wait()必须等待任意一个子进程的结束,只要有子进程结束,那么wait()就返回,如果没有子进程结束,父进程继续等待。waitpid()可以等待多种方式的子进程,也可以一个都不等待,因此更灵活。

    wait()和waitpid()能回收僵尸子进程的资源。

    pid_t wait(int* status)

    功能:等待任意一个子进程的结束,并取得退出状态和退出码参数:

    status是传出参数,返回子进程的退出状态和退出码返回值:返回结束子进程的PID

    宏函数被用于判断子进程的退出状态和获取退出码WIFEXITED(status) 判断是否正常退出WEXITSTATUS(status)获取退出码(只有正常退出才有效)

    5 int main()

    6{

    7 pid_t pid = fork();

    8 if(pid==0){//子进程分支

    9 sleep(2);

    10 printf("子进程%d开始运行\n",getpid());

    11 sleep(2);

    12 printf("子进程%d结束\n",getpid());

    13 exit(10);

    14 }

    15 int status;

    16 pid_t wpid= wait(&status);

    17 if(WIFEXITED(status))

    18 {

    19    printf("子进程%d结束,退出码%d\n",wpid,WEXITSTATUS(status));

    20 }

    21 printf("父进程结束\n");

    22

    运行结果:

    子进程14587开始运行

    子进程14587结束

    子进程14587结束,退出码10

    父进程结束

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

    功能:等待子进程的结束,但比wait()更灵活(可以不等)

    第一个参数:pid是等待哪个/哪些子进程,包括:

    -1 等待任意一个子进程的结束

    >0 等待特定的一个子进程(进程ID=pid)

    0  等待和父进程一个进程组的子进程(本组)

    <-1等待指定进程组的子进程(进程组ID=|pid|)

    第二个参数:status和wait()中的一样

    第三个参数:option可以设置等待或是不等待,默认0为等待,宏WNOHANG可以代表不等待。

    返回:有子进程结束返回结束子进程的PID,如果不等待并且没有子进程结束返回0,失败返回-1。

    int main()

    7 {

    8    pid_t pid1,pid2;//一父二子需要判断

    9 pid1 = fork();

    10

    11 if(pid1>0)pid2 = fork();

    12  if(pid1==0){//进程1

    13  sleep(1);

    14  printf("子进程-%d结束\n",getpid());

    15  exit(20);

    16  }

    17 if(pid2==0) {

    18 sleep(3);

    19 printf("子进程-%d结束\n",getpid());

    20 exit(20);

    21 }

    22 int status;

    23 pid_t wpid = waitpid(pid1,&status,0);

    24 if(WIFEXITED(status))

    25 {

    26 printf("子线程%d,退出码%d\n",wpid,WEXITSTATUS(status));

    27 }

    28 }

    vfork() +execl()创建子进程

    fork()函数从语法上和fork()没有任何区别,区别在于fork()不会复制父进程的任何资源。子进程会占用父进程的资源继续运行,而父进程会阻塞,停止运行。父进程的阻塞有两种方法可以解除

    1.子进程运行结束,把资源还给父进程

    2.子进程调用了execl(),启动了一个全新的程序,也把原来的资源还给父进程(并行的方式)。

    第二种方法更有意义更常用,第一种方法没有实际意义。

    vfork()会创建一个新的子进程,可以确保子进程先运行。

    vfork()创建的子进程必须用exit()退出,return语句退出会有问题。

    vford()函数能创建子进程,但是不能提供代码和数据,execl()函数不能创建子进程,但可以提供进程运行的代码和数据。

    execl()函数不会创建新的进程,进程PID不变,用一个新的程序替换掉当前进程执行的程序。

    int execl(char* path,char* cmd,...)

    功能:启动一个全新的程序,当前程序将被替换,但不会建立新进程

    参数:path就是新程序的路径,包括文件名,不能出错

    cmd就是运行程序的命令,比如:a.out

    ...可以包括命令的参数/命令的选项,最后以NULL结束

    返回:成功则启动新程序,没有任何返回值

    失败就无法启动新程序,返回-1

    关于进程必须会写代码:

    fork()

    vfork()和execl()

    相关文章

      网友评论

          本文标题:linux-08-进程管理2

          本文链接:https://www.haomeiwen.com/subject/xgvprttx.html