在Linux下,当进程结束时如何获得通知?

Ka *_* Rl 5 c c++ linux operating-system process

如何监视多个进程,如果一个进程结束,我想运行一些代码。

我发现了几个使用轮询来实现此目的的示例,但我正在寻找一种在进程终止时被推送的方法(可能由OS推送)。使用C或C ++是否可能?它可以在任何现代Linux上运行。

如果有机会,我想不需要root特权就可以这样做。

编辑:

整个程序的工作是监视这些过程,并将此信息发送到另一台服务器,然后将其集成到网站中。

我尚未启动这些过程,但可以确保以同一用户身份启动它们。

我认为应该可以,因为Linux下的top / ps命令还会为您提供有关尚未启动的进程的信息。

Bas*_*tch 7

通常,在 Linux 上,您无法收到有关非子进程或进程组或会话之外的进程的通知(使用waitpid(2)SIGCHLD-see signal(7) - ...)。

在某些 Linux 上,您的(非根)进程甚至可能不被允许查询其他进程的存在。

当然,有/proc/(每个进程有一个数字命名的目录,例如/proc/1234/pid 1234 的进程,请参阅proc(5))您可能会定期扫描(例如使用readdir(3) ...),但您无法收到通知(见的inotify(7) ,这确实不工作,像伪文件系统/proc/......关于里面的变化)。请注意,这/proc/是一个伪文件系统,访问它不涉及任何磁盘 IO,因此速度非常快。

所以你可以做的是扫描/proc/用每隔几秒钟 执行opendir(3) ,readdirclosedir(3) 睡眠(3)在一个循环中。顺便说一句,理论上不是万无一失的(原则上,实际上并非如此,内核可能会在几秒钟内重用相同的 pid),并且可能不会捕获所有短期进程(例如lsshell 命令)。

这种定期扫描/proc很可能是top(1)实用程序正在执行的操作。您可以通过深入研究其源代码top或通过strace(1)对其进行检查。

如果您的 C 代码已经知道某个进程的 pid 并且只是想检查该进程是否存在,则可以使用信号编号为 0 的kill(2)

另请参阅systemd凭据(7)

如果您可以更改被监视程序的代码或替换它们(例如,通过您的小 C 程序包装它们),事情就大不相同了;例如,你可以替换/usr/bin/foo/usr/local/bin/foo-wrapper和码的foo-wrapper.c哪个fork-s&exec-s原始/usr/bin/foo然后waitpid函数(2)在其上,最后发送(2)写(2)上的一些一些消息插座(7)FIFO(7)管( 7),并在监视器中使用基于poll(2)事件循环。如果您可以fork通过监视器获取所有程序,那么事情也会有所不同(使用waitpid...)。请参阅我的execicar.c程序以获取灵感。


Ade*_*med -3

请注意 /proc/ 目录保存每个正在运行的进程 PID 的目录,例如 /proc/1 是 PID 1

在该目录下有一个cmdline文件,可用于确定PID的命令,即:cat /proc/1/cmdline /usr/lib/systemd/systemd

你可以遍历/proc/[09]*目录来寻找与你要查找的内容相匹配的cmdline,当你匹配该命令时,你可以简单地检查cmdline是否仍然与原始的相匹配(相同的PID可以用于另一个进程(如果已终止)

这是完成该工作的一段简单代码:我还没有编写大部分错误纠正(如果找不到应用程序,程序会崩溃,其他一些错误会导致段错误)#include #include #include

int main(int argc, char* argv[]) {
  if (argc != 2){
    printf("usage:\nproc <processname>\n");
    return 2;
  }
  char * processName = argv[1];
  int pid = 0;
  FILE *processFile;
  char *monitoredProcess;
  DIR *root;
  struct dirent *dir;
  root = opendir("/proc/");
if (root)
  {
    int reading = 0;
    while((dir=readdir(root))!=NULL && reading==0)
    {
     // printf("dir name:%i\n",dir->d_ino);
      if (dir->d_name[0] > 47 && dir->d_name[0] < 58) {
    char directory[128];
    strcpy(directory,"/proc/");
        strcat(directory,dir->d_name);
    strcat(directory,"/cmdline");
    processFile = fopen(directory,"r");
    if (processFile == NULL) {
      printf("Error");
      return 1;
    }
    char line[2048];
    while (fgets(line, sizeof line, processFile) != NULL) {
      if(strstr(line,processName)) {
        printf("%s\n",directory);
        monitoredProcess = directory;
        reading = 1;
      }
      //the pid has been determined at this point, now to monitor
    }
      }
    }
    //monitoring
    printf("monitoring %s\n",monitoredProcess);
    while(processFile=fopen(monitoredProcess,"r")) {
      char line[2048];
      while (fgets(line, sizeof line, processFile) != NULL) {
    if(strstr(line,processName) == NULL)
      printf("application terminated\n");
      }
      sleep(3);
      fclose(processFile);
    }
  } else
    printf("unable to open folder\n");
}
Run Code Online (Sandbox Code Playgroud)