【问题标题】:Can't see program's output in the terminal after using fork and pipe in c在 c 中使用 fork 和 pipe 后在终端中看不到程序的输出
【发布时间】:2016-08-05 21:28:58
【问题描述】:

我应该编写一个程序来创建 2 个进程,用管道将它们连接起来,并在给定时间后结束这两个进程并终止。 其中一个程序将写入管道,另一个程序将从管道中读取并将其打印到 STDOUT。 首先将调用读取进程,然后将 pid 传递给第二个进程,因此它将向第一个进程发出 SIGUSR1 信号,告诉它读取。 出于某种原因,我从未在第一个进程的终端中看到输出, 此外,它甚至不打印行:“trying to exec1\n”,这是我为打印的进程调用“execlp”的地方。 这是 3 个程序的代码:

主程序:

#define STDERR 2
#define STDOUT 1
#define STDIN 0
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void alarmHandler(int sig);
void systemError();

char * intToString(int num , char number[4]);

static pid_t processId1, processId2;

int main(int argc, char ** argv){
    pid_t pid1, pid2;
    sigset_t block_mask1;
    struct sigaction exitSig;
    sigfillset(&block_mask1);
    exitSig.sa_handler = alarmHandler;
    exitSig.sa_mask = block_mask1;
    exitSig.sa_flags  = 0;
    sigaction(SIGALRM, &exitSig, NULL);
    if (argc < 2){
            systemError();
    } else {
        int x = atoi(argv[1]);
        alarm(x);
    }
    int fields[2];
    if (pipe(fields)){
        systemError();
    }

    if ((pid1 = fork()) == 0){
        printf("trying to exec1\n");
        close(STDIN);
        dup(fields[0]);
        close(fields[0]);
        close(fields[1]);
        if(execlp("./ex2_inp", "./ex2_inp", NULL)){
            systemError();
        }
    } else {
        processId1 = pid1;
        if ((pid2 = fork()) == 0){
            char number[350];
            printf("trying to exec2\n");
            close(STDOUT);
            dup(fields[1]);
            close(fields[0]);
            close(fields[1]);
            char * pidString = intToString(processId1, number);
            if(execlp("./ex2_upd","./ex2_upd",pidString, NULL)){
                systemError();
            }
        } else{
            processId2 = pid2;
        }
    }

    close(fields[0]);
    close(fields[1]);
    pause();
    return 1;
}

/***********************
 * handler for alarm signal
 *************************/
void alarmHandler(int sig){
    kill(processId2, SIGINT);
    kill(processId1, SIGINT);
    exit(1);
}

/***********************
 * turn pid to string
 *************************/
char * intToString(int num , char number[350]){
    sprintf(number, "%d", num);
    return number;
}

ex2_inp:

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){

    sigset_t block_mask1, block_mask2;
    struct sigaction exitSig, print;
    sigfillset(&block_mask1);
    sigfillset(&block_mask2);
    exitSig.sa_handler = exitHandler;
    print.sa_handler = printHandler;
    print.sa_mask = block_mask2;
    exitSig.sa_mask = block_mask1;
    exitSig.sa_flags  = 0;
    print.sa_flags = 0;
    sigaction(SIGINT, &exitSig, NULL);
    sigaction(SIGUSR1, &print, NULL);
    pause();
    return 1;
}

void exitHandler(int sig){
    printf("exiting1!\n");
    close(1);
    exit(1);
}

void printHandler(int sig){
    char * buffer[80];
    read(1, buffer, 80);
    printf("%s", buffer);
}

ex2_upd:

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);

int main(int argc, char * argv[]){
    sigset_t block_mask1;
    struct sigaction exitSig;
    sigfillset(&block_mask1);
    exitSig.sa_handler = exitHandler;
    exitSig.sa_mask = block_mask1;
    exitSig.sa_flags  = 0;
    sigaction(SIGINT, &exitSig, NULL);
    printf("2's message\n");
    kill(atoi(argv[1]), SIGUSR1);
    pause();
    return 1;
}

void exitHandler(int sig){
    printf("exiting2!\n");
    close(0);
    exit(1);
}

谢谢

【问题讨论】:

  • 在调用printf 之后和调用close 之前尝试使用fflush(stdout);,以确保打印传递给printf 的内容。
  • 它没有帮助,我仍然没有看到我应该得到的“2's message\n”,由第一个进程打印
  • printf() 不是异步安全的。此外,您打算发送信号的方式是竞争条件。该信号可能在接收者调用sigaction()之前发送。
  • 有什么方法可以确保在那之前没有发送?谢谢
  • 我会先学习 C 的基础知识,而不是多编程。

标签: c process pipe signals fork


【解决方案1】:

ex2_upd.c:

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);

int main(int argc, char * argv[]){
    sigset_t block_mask1;
    struct sigaction exitSig;
    sigfillset(&block_mask1);
    exitSig.sa_handler = exitHandler;
    exitSig.sa_mask = block_mask1;
    exitSig.sa_flags  = 0;
    sigaction(SIGINT, &exitSig, NULL);
    printf("2's message\n");
    kill(atoi(argv[1]), SIGUSR1);
    sleep(1); /* This was pause - causing ex2_inp read() to wait forever, since read() on pipe needs to either fill buffer or END_OF_FILE, unless we make the filedescriptor in the read-end non-blocking via fcntl()  */
    return 1;
}

void exitHandler(int sig){
    printf("exiting2!\n");
    close(0);
    exit(1);
}

ex2_inp.c:

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){

    sigset_t block_mask1, block_mask2;
    struct sigaction exitSig, print;
    sigfillset(&block_mask1);
    sigfillset(&block_mask2);
    exitSig.sa_handler = exitHandler;
    print.sa_handler = printHandler;
    print.sa_mask = block_mask2;
    exitSig.sa_mask = block_mask1;
    exitSig.sa_flags  = 0;
    print.sa_flags = 0;
    sigaction(SIGINT, &exitSig, NULL);
    sigaction(SIGUSR1, &print, NULL);
    pause();
    return 1;
}

void exitHandler(int sig){
    printf("exiting1!\n");
    close(1);
    exit(1);
}

void printHandler(int sig){
    char buffer[80]; /* removed * */
    read(0, buffer, 80);   /* stdin is fd=0, not 1 */
    printf("-> %s <-\n", buffer); /* added \n, forces new-line */
}

【讨论】:

    猜你喜欢
    • 2021-12-07
    • 2014-06-09
    • 2013-05-28
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 2012-09-12
    相关资源
    最近更新 更多