exit()与wait-()函数

这节的知识我就基本只是把书上的整理了一下, 仅仅只是个人觉得有用的整理了下。

exit()函数

  • _Exit() : 其目的是为进程提供一种无需运行终止处理程序或信号处理程序而终止的方法
  • _exit() : _exit()由exit()调用,处理UNIX特定的细节
  • 最后一个进程调用return等其他终止的返回值并不作为进程的返回值. 当最后一个进程从启动例程返回时, 该进程以终止状态0返回.
  • 终止
不管进程是怎么终止的, 最后都会调用内核的同一段代码. 这段代码会关闭所有的流操作, 释放所使用的存储器.
在异常终止时, 系统会返回一个异常终止状态.
父进程通过wait()watipid()函数来获得终止状态.
在最后调用exit()时, 转化为终止状态
在父进程比子进程先终止时,父进程会改变为init进程(也是之前说的init会成为所有孤进程的父进程(原因 :在进程终止时, 内核逐个检查所有活动的进程, 以判断是不是正要终止进程的子进程, 如果是, 则该进程的父进程ID改为1.)
由init收养的父进程是不会变为僵尸进程的(僵尸进程 : 一个已终止, 但是其父进程没有对其做善后处理)

wait*()函数

wait()

  1. pid_t wait(int *statloc)
    • 子进程运行时, wait使调用者堵塞
    • statloc != NULL 则进程的终止状态就存放在其所指的单元, statloc == NULL 则不关心其终止状态
    • 当一个子进程终止就立刻返回。

waitpid()

  1. pid_t waitpid(pid_t pid, int *statloc, int options)
    • 可以并不堵塞
    • 可以等待pid指定的进程终止在执行waitpid()的调用者。
    • statloc != NULL 则进程的终止状态就存放在其所指的单元, statloc == NULL 则不关心其终止状态
    • pid的值
      pid == -1 等待任意子进程
      pid > 0 等待 “进程ID == pid” 的进程
      pid == 0 等待 ”组ID == 调用进程组ID”的任意进程
      pid < -1 等待 “组ID == |pid|“ 的进程

如果一个进程fork一个子进程, 但是想等待子进程终止再进行, 也不希望子进程处于僵尸状态直到父进程终止, 这就需要调用两次fork() (通俗一点就是希望父进程在子进程之前终止)

  
  
  1. /*************************************************************************
  2. > File Name: fork_wait_子进程.cpp
  3. > Author: Function_Dou
  4. > Mail:
  5. > Created Time: 2018年01月30日 星期二 11时23分27秒
  6. pid_t waitpid(pid_t pid, int *statloc, int options)
  7. 可以并不堵塞
  8. 可以等待pid指定的进程终止在执行waitpid()的调用者。
  9. statloc != NULL 则进程的终止状态就存放在其所指的单元, statloc == NULL 则不关心其终止状态
  10. pid的值
  11. pid == -1 等待任意子进程
  12. pid > 0 等待 “进程ID == pid” 的进程
  13. pid == 0 等待 ”组ID == 调用进程组ID”的任意进程
  14. pid < -1 等待 “组ID == |pid|“ 的进程
  15. ************************************************************************/
  16. #include <stdio.h>
  17. #include "apue.h"
  18. #include <sys/wait.h>
  19. int main(void)
  20. {
  21. // pid_t pid = -1;
  22. pid_t pid;
  23. if((pid = fork()) < 0)
  24. err_sys("fork error");
  25. else if(pid == 0)
  26. {
  27. if((pid = fork()) < 0)
  28. err_sys("fork error");
  29. else if(pid > 0)
  30. exit(0);
  31. sleep(2);
  32. printf("second child, parent pid = %ld\n", (long)getppid());
  33. exit(0);
  34. }
  35. if(waitpid(pid, NULL, 0) != pid)
  36. err_sys("waitpid error");
  37. exit(0);
  38. }
  39. /* 样例
  40. [root@192 Process]# ./a.out
  41. [root@192 Process]# second child, parent pid = 1
  42. [root@192 Process]#
  43. */
说明
WIFEXITED正常终止(真)可执行WEXITSTATUS 来获取子进程传递给exit, _exit参数
WIFSIGNALED异常终止(真)可执行WTERMSIG 获取子进程终止的信号编号
WIFSTOPPED暂停子进程的返回的状态(真)WSTOPSIG 获取子进程暂停的信号编号
  
  
  1. /*************************************************************************
  2. > File Name: exit__退出状态.cpp
  3. > Author: Function_Dou
  4. > Mail:
  5. > Created Time: 2018年01月31日 星期三 21时40分13秒
  6. ************************************************************************/
  7. #include <stdio.h>
  8. #include "apue.h"
  9. #include <sys/wait.h>
  10. void pr_exit(int status)
  11. {
  12. // 正常终止
  13. if(WIFEXITED(status))
  14. printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
  15. // 异常终止
  16. else if(WIFSIGNALED(status))
  17. printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
  18. #ifdef WCOREDUMP
  19. WCOREDUMP(status) ? " (core file generated)" : "");
  20. #else
  21. "");
  22. #endif
  23. // 暂停子进程
  24. else if(WIFSTOPPED(status))
  25. printf("child stopped, signal number = %d", WSTOPSIG(status));
  26. }
  27. int main(void)
  28. {
  29. pid_t pid;
  30. int status;
  31. // 1
  32. if((pid = fork()) < 0)
  33. err_sys("fork error");
  34. else if(pid == 0)
  35. exit(7);
  36. if(wait(&status) != pid)
  37. err_sys("wait error");
  38. pr_exit(status);
  39. // 2
  40. if((pid = fork()) < 0)
  41. err_sys("fork error");
  42. else if(pid == 0)
  43. abort();
  44. if(wait(&status) != pid)
  45. err_sys("wait error");
  46. pr_exit(status);
  47. // 3
  48. if((pid = fork()) < 0)
  49. err_sys("fork error");
  50. else if(pid == 0)
  51. status /= 0;
  52. if(wait(&status) != pid)
  53. err_sys("wait error");
  54. pr_exit(status);
  55. exit(0);
  56. }
  57. /* 样例
  58. ./a.out
  59. normal termination, exit status = 7
  60. abnormal termination, signal number = 6 (core file generated)
  61. abnormal termination, signal number = 8 (core file generated)
  62. */

竞争条件

竞争条件 : 当多个进程对共享数据进行某种处理, 但是最后结果又得取决于进程运行的顺序。(通俗一点就是运行还得看系统的调度顺序)

轮询:等待父进程终止在进行子进程。(消耗cpu资源)

  
  
  1. while(getppid != 1)
  2. sleep(1);

竞争条件的程序

  
  
  1. /*************************************************************************
  2. > File Name: TELL_WAIT_竞争条件.cpp
  3. > Author: Function_Dou
  4. > Mail:
  5. > Created Time: 2018年01月31日 星期三 22时38分46秒
  6. int putc(int ch, FILE *stream);
  7. 参数ch表示要输入的位置,参数stream为要输入的流。
  8. 若正确,返回输入的的字符,否则返回EOF。
  9. ************************************************************************/
  10. #include <stdio.h>
  11. #include "apue.h"
  12. static void charatatime(char *);
  13. int main(void)
  14. {
  15. pid_t pid;
  16. // 修改方法2
  17. // TELL_WAIT();
  18. // 修改方法1
  19. // if((pid = vfork()) < 0) 没有竞争关系了, 因为先进行子进程
  20. if((pid = fork()) < 0)
  21. err_sys("fork error");
  22. else if(pid == 0)
  23. {
  24. // 修改方法2
  25. // WAIT_PARENT();
  26. charatatime("one chile\n");
  27. }
  28. else
  29. {
  30. // 修改方法2
  31. // TELL_CHILD(pid);
  32. charatatime("first parent\n");
  33. }
  34. exit(0);
  35. }
  36. static void charatatime (char *str)
  37. {
  38. char *ptr;
  39. int c;
  40. setbuf(stdout, NULL);
  41. for(ptr = str; (c = *ptr++) != NULL; )
  42. putc(c, stdout);
  43. }
  44. /* 样例
  45. [root@192 Process]# ./a.out
  46. first oparent
  47. ne chile
  48. [root@192 Process]# ./a.out
  49. first paronent
  50. e chile
  51. [root@192 Process]# ./a.out
  52. first parenot
  53. ne chile
  54. */

每次的结果不一样, 因为这个要跟此时的进程顺序有关。
书上的修改方法2运行有问题, 因为那些函数没有包含进去, 所以无法测试。

看样子导出html格式代码就都有高亮了。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值