从进程发送信号到控制终端

从进程发送信号到控制终端

我想知道一种干净优雅的方法来执行以下操作:假设我编写了一个名为 的 C++ 程序,foo作为名为 的 shell 脚本的一部分在内部运行bar.sh。我想让 shell 脚本foo作为后台进程运行,然后等待直到执行foo到达我选择的一行,此时bar应继续执行。

为了清楚起见,这里有一个虚拟示例bar.sh

#!/bin/bash
./foo
wait 
echo "WAKING UP"

这是foo

#include <iostream>
 int main(){
    for (int i = 0; i < 1000000; i++){
          std::cout << i << std::endl;

          if (i == 50){
              //Wake up bash!
          }
    }
 }

我想修改foo和/或bar以便等待命令将在迭代 50bar时停止。foo因此,当 for 循环到达 时fooi = 50应该bar唤醒并打印 WAKING UP。当然也foo可以继续保持运行。

我该如何修改这些程序才能达到这种效果?

答案1

fork()这基本上就是+的目的setsid()

酒吧.sh

#!/bin/bash

echo "Launching foo"
./foo
echo "Waking up"

foo.c

#include <stdio.h>
#include <unistd.h>


int main(int ac, char ** av)
{
    int pid;
    for (int i=0; i<5; i++) {
        sleep(1);
    }
    printf("OK, we count to 5.\n");

    /* 
     * Here we fork() + setsid() to detach from parent process
     * Return value of fork is 0 if you are in child, pid of the child 
     * if you're in the parent process 
     */
    pid = fork();
    if (pid == 0) {
        setsid();
        printf("We forked, still running but shell may be back\n");
        sleep(5);
        printf("Exiting ...\n");
    } else {
        return 0;
    }
}

结果

/tmp/pouet$ ps aux|grep foo
me  8595  0.5  0.1 217548 18576 pts/12   T    14:17   0:01 vim foo.c 
me  9167  0.0  0.0  12716   912 pts/12   S+   14:21   0:00 grep foo
/tmp/pouet$ ./bar.sh 
Launching foo
OK, we count to 5.
We forked, still running but shell may be back
Waking up
/tmp/pouet$ ps aux|grep foo
me  8595  0.5  0.1 217548 18576 pts/12   T    14:17   0:01 vim foo.c 
me  9189  0.0  0.0   4160    76 ?        Ss   14:21   0:00 ./foo 
me  9192  0.0  0.0  12716   940 pts/12   S+   14:21   0:00 grep foo
/tmp/pouet$ Exiting ...

/tmp/pouet$ ps aux|grep foo
me  8595  0.5  0.1 217548 18576 pts/12   T    14:17   0:01 vim foo.c
me  9212  0.0  0.0  12716   908 pts/12   S+   14:21   0:00 grep foo

答案2

一种方法是先fork离开父母。

#include <iostream>
#include <unistd.h>
#include <stdlib.h>

int main(){
    for (int i = 0; i < 1000000; i++){
        std::cout << i << std::endl;

        if (i == 50){
            if (fork() != 0) {
                _Exit(0);
            }
        }
    }
}

这可能会产生不良影响,使用_Exitis 可以避免最明显的影响。

另一种方法是 C++ 程序向父程序发送信号。这也会终止内置的等待(我不记得它是 POSIX 还是只是一个 bashism)。

#include <iostream>
#include <unistd.h>
#include <stdlib.h>

int main(){
    for (int i = 0; i < 1000000; i++){
        std::cout << i << std::endl;

        if (i == 50){
            kill(getppid(), SIGINT);
        }
    }
}

这里需要注意的一件事是脚本和C++程序之间的过程。您可能想寻找trap一种在 shell 脚本中处理信号的方法。

相关内容