【问题标题】:linux - exec'd program not terminatinglinux - 执行程序未终止
【发布时间】:2016-12-02 19:16:51
【问题描述】:

我正在 Linux 上用 C 语言编写程序,它必须派生 2 个孩子。

第一个孩子将通过管道向第二个孩子发送两个随机数。它将侦听 SIGUSR1 信号,然后终止。

第二个孩子将复制(dup2)管道输入作为 STDIN 和文件 fp 作为 STDOUT。然后它将执行程序,该程序将根据其输入打印出一些数据并结束。

我的问题是,execl 的程序永远不会终止,我不知道为什么。任何帮助或提示将不胜感激。

ma​​in.c(父):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>

const int BUFFER_SIZE = 30;

int pipefd[2] = {0,0};
int parent_pid = 0;
int first_pid = 0;
int second_pid = 0;
int sleep_time = 5;
int debug = 0;
FILE *fp;

void parent_func() {
    int wstatus = 0;

    sleep(sleep_time);
    kill(first_pid, SIGUSR1);
    wait(&wstatus);
    waitpid(second_pid, &wstatus, 0);
}

static void sigusr1_handler(int sig) {
    if (sig == SIGUSR1) {
        fputs("TERMINATED", stderr);
        close(pipefd[1]);
        exit(0);
    }
}

void first_func() {
    struct sigaction act;
    char buffer[BUFFER_SIZE];

    close(pipefd[0]);                                                                                                                                        
    memset(&act, '\0', sizeof(act));    // clear the sigaction struct                                                                                        

    act.sa_handler = &sigusr1_handler; // sets function to run on signal                                                                                      

    if (sigaction(SIGUSR1, &act, NULL) < 0) {   // assign sigaction                                                                                          
        fputs("cannot assign sigaction - exiting...", stderr);                                                                                               
        exit(1);                                                                                                                                             
    }                                                                                                                                                        

    while (1) {                                                                                                                                              
        sprintf(buffer, "%d %d\n", rand(), rand());                                                                                                          
        write(pipefd[1], buffer, strlen(buffer));                                                                                                            
        puts(buffer);                                                                                                                                        
        sleep(1);                                                                                                                                            
    }                                                                                                                                                                                    
}                                                                                                                                                            

void second_func() {                                                                                                                                         
    close(pipefd[1]);                                                                                                                                        
    fp = fopen("out.txt", "w");                                                                                                                              
    char buf[30];

    dup2(pipefd[0], STDIN_FILENO);
    close(pipefd[0]);
    //dup2(fileno(fp), STDOUT_FILENO); 

    execl("./test", "", NULL);
    perror("Error");
}

int main(int argc, char *argv[]) {
    int fork_val = 0;
    parent_pid = getpid();

    if (pipe(pipefd)) {
        fputs("cannot create pipe - exiting...", stderr);
        return 1;
    }

    if (debug) {
        sleep_time *= 10;
    }

    if ((fork_val = fork()) == -1) {
        fputs("cannot fork process - exiting...", stderr);
        return 1;
    } else if (fork_val == 0) {
        first_func();
    } else {
        first_pid = fork_val;
        if ((fork_val = fork()) == -1) {
            fputs("cannot fork process - exiting...", stderr);
            return 1;
        } else if (fork_val == 0) {
            second_func();
        } else {
            second_pid = fork_val;
            parent_func();
        }
    }
    fclose(fp);
    exit(0);
}

test.c(执行后的文件):

#include "nd.h"
#include "nsd.h"
#include <stdio.h>
#include <stdlib.h>

int main() {
    int num1 = 0;
    int num2 = 0;
    char buffer[100];

    while (fgets(buffer, 100, stdin) != NULL) {
       if (sscanf(buffer, "%d %d", &num1, &num2) == 2) {
           (num1 < 0) ? num1 = (num1 * -1) : num1;
           (num2 < 0) ? num2 = (num2 * -1) : num2;
           if (num1 == 1 || num2 == 1) {
               puts("1");
           } else if (num1 == num2) {
               if (nd(num1) == 1) {
                   puts("prime");
               } else {
                   printf("%d\n", num1);
               }
           } else if (nd(num1) == 1 && nd(num2) == 1) {
               puts("prime");
           } else {
               printf("%d\n", nsd(num1, num2));
           }
       } else {
          fputs("error\n", stderr);
       } 
    }
    fputs("DONE", stderr);
    exit(0);
}

【问题讨论】:

标签: c linux


【解决方案1】:

为了能够从管道中检测文件的结尾,您需要从没有写入器的空管道中读取(没有打开用于写入描述符的进程)。

由于您的编写器 (first_func()) 永远不会关闭其描述符,并且总是在一个永无止境的循环中写入一些内容,因此阅读器将等待一些数据或读取一些数据。

还要小心关闭无用的描述符,否则你可能会遇到管道问题,例如只有一个进程是读取器和写入器,因此无法检测到文件的结尾......

【讨论】:

  • 谢谢,我忘了在父进程中关闭管道。但是 first_func() 中的管道由 sigusr1_handler() 关闭,它通过从父进程发送信号来调用。
猜你喜欢
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多