【问题标题】:How to send a kill signal to multiple child processes in case of failure doing a task?如果执行任务失败,如何向多个子进程发送终止信号?
【发布时间】:2017-04-06 18:28:15
【问题描述】:

我正在尝试制作一个最多可创建 4 个子进程的程序。每个孩子将使用搜索功能在所需文件中查找某个单词:

bool 搜索(char *file,char *word,int 部分)

PS:你可以忽略搜索功能,它究竟做什么,因为这里的主要任务是在某个子进程成功时向多个子进程发送信号。

每个子进程都会在文件的某个部分进行搜索。即一个名为“foo”的文件,其中包含:

汽车

酒吧

焦油

子进程正在寻找字符串“bar”。

如果子进程成功找到字符串,它将以值 0 退出(exit(0)),否则如果它完成了整个部分但没有成功找到字符串,它将退出值为 1(exit(1))。

一旦存在值为 0 的孩子(成功找到字符串)。父进程会向其他子进程发送终止信号。

考虑以下代码:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main()
{
    pid_t p;
    p=fork();
    int i;
    int storage[4];
    for(i=0;i<4;i++)
    {
        p=fork();
        if(p==0)
        {
            storage[i]=getpid();
            open("testfile.txt",O_WRONLY);
            if(search("testfile.txt","bar",i))
            {
                storage[i]=1;
                //exit(0);
            }
            else
                //exit(1);
        }
    }
    
    for(i=0;i<4;i++)
    {
        if(storage[i]!=1)
            kill(stroage[i],SIGTERM);
    }
}

我在这段代码中所做的是使用一个由 4 个整数组成的数组,它包含子进程的 ID。子成功的情况改为1。之后我向除该特定进程之外的其他进程发送了终止信号。

我写的代码正确吗?如果是这样,如何在不使用数组的情况下使用退出值发送信号?

【问题讨论】:

  • storage 是一个具有自动存储期限的对象。它肯定不会在进程之间共享,因此您的方法绝对行不通。
  • @EOF 我想我明白了,4个子进程将有自己的变量存储的内存字段,对吧?这就是为什么它不起作用,因为父级在变量中没有值?如果我将它用作指针怎么办?这样能解决吗?
  • 只有指向进程间共享内存的指针才能解决这个问题。在这种情况下,您还必须确保访问共享内存的原子性和顺序。
  • 除了已经说明的问题之外,无论如何,即使可能,这种方法也只有在所有进程完成运行后才可行,因为在它们全部完成执行之前,您不会知道仍在执行的其中一个是否将以状态码 1 退出,但还没有这样做。由于您必须等待它们全部执行完毕,因此您根本不需要向它们发送任何信号。
  • @PaulGriffiths 我不是在等待它们全部完成,只有一个必须以状态码 0 完成,然后父进程将向尚未完成的其他进程发送终止信号(有些人可能会以状态码 1 结束,然后以状态码 0 结束,这是不成功的)。

标签: c signals fork


【解决方案1】:

如果您不想使用数组,可以运行 unix 命令以使用 cmd() 获取子进程 ID 的列表。

fork() 也将子进程 ID 返回给父进程。父级可以将其存储在数组中。

【讨论】:

    【解决方案2】:

    您可以尝试将孩子的 pid 存储在共享内存中的数组中,为此您可能应该创建具有以下内容的单独 .h 文件。

    struct shared_arr {
        int is_full;
        int pids_arr[4];
    };
    

    您可以使用以下 sn-p 访问该共享结构:

    int shm_id = shmget((key_t) 12345, sizeof(struct shared_arr), 0666| IPC_CREAT);
    
    //get the shared data
    struct shared_arr *shared_data;
    void* shared_memory = (void*) 0;
    shared_memory = shmat(shm_id, (void*)0,0);
    if(shared_memory == (void *) -1) {
        fprintf(stderr, "shmat FAILED\n");
    }
    shared_data = (struct shared_arr *) shared_memory;
    
    //init shared data with zeros
    for(int i = 0; i < MAX_SHARED_ARR_SIZE; i++) {
        shared_data->pids_arr[i] = 0;
    }
    

    详情:https://en.wikipedia.org/wiki/Shared_memory#Support_on_Unix-like_systems

    另外,考虑设置进程组 ID 并向同一进程组中的所有进程发送信号,只使用一次终止调用。

    关于设置组 ID 的详细信息:https://www.systutorials.com/docs/linux/man/2-setpgid/ 关于杀:http://man7.org/linux/man-pages/man2/kill.2.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 2023-03-28
      • 2018-05-31
      • 1970-01-01
      相关资源
      最近更新 更多