首页 > 社交 > 科普中国

Linux那些被你忽略的知识点

常驻编辑 科普中国 2022-09-19 进程   知识点   线程   函数   信号   参数   结束   文件   程序   系统   资源


ANu拜客生活常识网

注: wait就是经过包装的waitpid。ANu拜客生活常识网

static inline pid_t wait(int *wait_stat)
{
return waitpid(-1,wait_stat,0);
}

如果父进程属于守护进程一类,开启TCP套接字等待链接,每当有请求到来,便fork一个子进程传输信息并自由退出。父进程并不关注子进程的退出状态,是否正常都不影响今后的服务,但子进程变成僵尸进程便麻烦了,随着时间的进行,僵尸进程一大堆,虽然占用资源不多,且终究是个隐患。此时可以利用信号处理方式进行非阻塞回收僵死子进程资源。ANu拜客生活常识网

例子(子进程状态改变会发送SIGCHLD信号给父进程,父进程创建并回收多个子进程):ANu拜客生活常识网

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MY_PROCESS_COUNT 10 
void child_catch(int signalNumber) {
  //子进程状态发生改变时,内核对信号作处理的回调函数
  int w_status;
  pid_t w_pid;
  while ((w_pid = waitpid(-1, &w_status, WNOHANG)) != -1 && w_pid != 0) {
    if (WIFEXITED(w_status)) //判断子进程是否正常退出
      printf("---catch pid %d,return value %d
", w_pid, WEXITSTATUS(w_status)); //打印子进程PID和子进程返回值
  }
}
int main(int argc, char **argv) {
  pid_t pid;
  int i;
  //在此处阻塞SIGCHLD信号,防止信号处理函数尚未注册成功就有子进程结束
  sigset_t child_sigset;
  sigemptyset(&child_sigset); //将child_sigset每一位都设置为0
  sigaddset(&child_sigset, SIGCHLD); //添加SIGCHLD位
  sigprocmask(SIG_BLOCK, &child_sigset, NULL); //完成父进程阻塞SIGCHLD的设置 
  for (i = 0; i < MY_PROCESS_COUNT; i++) {
    //创建子进程,创建成功就跳出循环
    if ((pid = fork()) == 0)
      break;
  }
  if (MY_PROCESS_COUNT == i) { //括号内为父进程代码
    struct sigaction act; //信号回调函数使用的结构体
    act.sa_handler = child_catch;
    sigemptyset(&(act.sa_mask)); //设置执行信号回调函数时父进程的的信号屏蔽字
    act.sa_flags = 0;
    sigaction(SIGCHLD, &act, NULL); //给SIGCHLD注册信号处理函数
    //解除SIGCHLD信号的阻塞
    sigprocmask(SIG_UNBLOCK, &child_sigset, NULL);
    printf("im PARENT ,my pid is %d
", getpid());
    while (1){ //父进程在这里处理自己的相关事情,同时回收僵死子进程资源
//父进程运行相关代码
        }
  } else {
    //子进程执行代码
    printf("im CHILD ,my pid is %d
", getpid());
    return i;
  }
}

特殊进程

  • - 僵尸进程:进程已运行结束,但进程占用的资源未被回收,这样的进程称为僵尸进程。子进程已运行结束,父进程未调用wait或者waitpid函数回收子进程的资源是 子进程变为僵尸进程的原因。
  • - 孤儿进程:父进程运行结束,但子进程未运行结束的子进程。(在bash终端上,父进程结束后即会释放终端,子进程其实是在后台运行的。)
  • - 守护进程:守护进程是个特殊的孤儿进程,这种进程脱离终端,在后台运行。

exit函数

#include 
void exit(int status)
参数:status是返回给父进程的参数(低8位有效)。

ANu拜客生活常识网

注:exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的。main函数结束时也会隐式地调用exit函数。exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。exit是结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程;而return是返回函数值并退出函数。通常情况:exit(0)表示程序正常, exit(1)和exit(-1)表示程序异常退出,exit(2)表示表示系统找不到指定的文件。在整个程序中,只要调用exit就结束(当前进程或者在main时候为整个程序)。ANu拜客生活常识网

_exit函数
#include 
void _exit(int status)
参数:status是返回给父进程的参数(低8位有效)。    

相关阅读:

  • 进程有哪些(查看进程)
  • 如何查看进程(应用程序进程)
  • 如何结束进程(笔记本电脑卡了怎么结束程序)
  • 怎么结束进程 怎么结束正在运行的程序?
  • liunx中jar包启动脚本
  • 北方体验版夏天结束 全国入夏进程图告诉你哪里是真正
  • 今年来最强降雨过程来袭 这份降雨进程图请收好
  • 怎么软化已经硬化的动脉血管?生活中做好这几点,或会有所
  • 从通用的协议栈层面来优化Redis性能的实践
  • 臭氧推动南大洋变暖进程的能力被低估
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。