• c 几种父进程主动终止子进程的方法


    一般的情况,子进程自己运行完后,执行exit 或者return 后,父进程wait.  waitpid收回子进程。但子进程是一个循环等待状态不主动退出,父进程可以采用下面几种方法。

    1.如子进程是循环状态

    子进程循环等待键盘的输入,如父进程模拟键盘输入一个字符,子进程收到就跳出scanf()。同理,如是socket 的accept()等待,也可以发送一字符,让子进程跳出等待。

    1. #include <string.h>
    2. #include <stdio.h>
    3. #include <fcntl.h>
    4. #include <linux/input.h>
    5. #include <linux/uinput.h>
    6. #include <stdio.h>
    7. #include <unistd.h>
    8. #include <wait.h>
    9. void mn_key(int fd,int kval)
    10. {
    11. struct input_event event;
    12. event.type = EV_KEY;
    13. event.value = 1;
    14. event.code = kval;
    15. write(fd,&event,sizeof(event)) ;
    16. event.type = EV_SYN;
    17. event.code = SYN_REPORT;
    18. event.value = 0;
    19. write(fd, &event, sizeof(event));
    20. memset(&event, 0, sizeof(event));
    21. event.type = EV_KEY;
    22. event.code = kval;
    23. event.value = 0;
    24. write(fd, &event, sizeof(event));
    25. event.type = EV_SYN;
    26. event.code = SYN_REPORT;
    27. event.value = 0;
    28. write(fd, &event, sizeof(event));
    29. }
    30. int main()
    31. { int stat;
    32. pid_t pid=fork();
    33. if(pid==0){
    34. while(1){
    35. char c[20];
    36. scanf("%s",c);
    37. if(!strcmp(c,"0")){ //接收到0字符,子进程退出
    38. puts("zjc over");
    39. return 0;
    40. }
    41. printf("zjc:%s\n",c);
    42. }
    43. }
    44. sleep(10); //10秒后,中止子进程的运行。
    45. int fd = open("/dev/input/event3",O_RDWR); //每个机器的event(n)可能不同。
    46. if(fd<=0){
    47. puts("keyboad error"); //dev/input/event3 权限chmod 777 要能读写
    48. return -1;
    49. }
    50. mn_key(fd,KEY_0);
    51. mn_key(fd,KEY_ENTER);
    52. mn_key(fd,KEY_ENTER); //不清楚为什麽要两行
    53. wait(&stat);
    54. close(fd);
    55. }

    2.上面的方法不通用,可以说是特例,下面的方法采用kill()函数,可以说是通用方法,采用管道先把子进程号传到父进程,再用kill函数。此方法非常暴力,直接杀死子进程,不管它是否结束。

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <arpa/inet.h>
    6. #include <sys/socket.h>
    7. #include <wait.h>
    8. #include <signal.h>
    9. #include <sys/prctl.h>
    10. #include <sys/types.h>
    11. int main(void){
    12. // int stat;
    13. int zf[2];
    14. pipe(zf); //此句必须放在fork()语句前
    15. pid_t pid=fork();
    16. if(pid==0){
    17. pid_t pid1=getpid();
    18. printf("z:%d\n",pid1);
    19. write(zf[1],&pid1,4);
    20. while(1){
    21. char c[10];
    22. scanf("%s",c);
    23. if(!strcmp(c,"~")){
    24. puts("zjc over");
    25. exit(0);
    26. }
    27. printf("%s\n",c);
    28. }
    29. }
    30. sleep(3);
    31. pid_t bz;
    32. read(zf[0],&bz,4); //父进程取得子进程号
    33. printf("f:%d\n",bz);
    34. kill(bz,1); //关闭子进程
    35. // wait(&stat);
    36. return 0;
    37. }

    3. 父进程用sigqueue() 发送终止信号,子进程signal() 收到父进程信号,改变循环标志位,退出循环,再退出子进程。此种方法文明不粗暴。此处父进程不能用raise函数,因为此函数只能向本进程发送信号。

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <arpa/inet.h>
    6. #include <sys/socket.h>
    7. #include <wait.h>
    8. #include <sys/types.h>
    9. #include <signal.h>
    10. int main(void){
    11. union sigval si;
    12. si.sival_int=0;
    13. int stat;
    14. pid_t zf[2];
    15. pipe(zf);
    16. pid_t pid=fork();
    17. if(pid==0){
    18. pid_t id=getpid();
    19. write(zf[1],&id,4);
    20. int t=1;
    21. void handle(int sig){
    22. printf("%d\n",sig);
    23. t=0;
    24. }
    25. signal(20,&handle);
    26. while(t){
    27. puts("zjc");
    28. sleep(1);
    29. }
    30. printf("%d\n",t); //t=0
    31. exit(0);
    32. }
    33. int bz;
    34. read(zf[0],&bz,4);
    35. sleep(2);
    36. sigqueue(bz,20,si);
    37. wait(&stat);
    38. return 0;
    39. }

    sigqueue可以为非子进程的不关联进程发信号,只要知道对方的进程号就行了,可以用有名管道把进程号先传给对方进程。突然想到,可不可以用这个发信号的方法来执行进程间的互斥等操作。多进程主要用于多任务,比如需要同时运行两个以上执行动作的场景。

    对于被安装信号的进程来讲,进程内代码执行与信号触发是异步的。信号好象是硬件的中断。条件产生了,操作系统就触发信号,执行信号的默认函数动作。执行完后,又继续执行进程的代码。

    信号可以安装在一个进程内,再由本进程触发完成动作,如定时。

    这个信号感觉非常有用,感觉这才是真正的多任务,进程间可以互不影响,一个进程完成某个动作后,触发信号通知另一个进程,(在触发信号之前,另一个进程可以干别的事情)。告诉它,我已完成,你可以怎么办。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    【Springboot】SpringBoot-Admin 服务监控+告警通知
    第三届 “鹏城杯”(初赛)
    MySQL知识点总结(七)——主从复制、读写分离、高可用
    Python:实现linear regression线性回归算法(附完整源码)
    Redis主从结构数据同步分析
    基于Java语言的网上订餐系统(附:源码 课件)
    Unity粒子系统ParticleSystem各模块及其参数学习
    Linux-文件压缩解压
    90%的软件测试从业者,努力的方向都错了...你呢?
    SQL设计时增加说明列
  • 原文地址:https://blog.csdn.net/m0_59802969/article/details/133808084