我试图使用管道将值从一个程序传递到另一个程序。
第一个程序创建一个管道然后使用fork创建一个子进程,并在子进程的一部分中使用execlp执行另一个程序。
我希望在使用管道运行时将第一个程序中的字符发送到另一个程序,但我不知道该怎么做,因为fd [2]仅在第一个程序中定义。
第一个程序的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <termios.h>
#include <signal.h>
char getch();
int main()
{
bool selected;
int fd[2],pid;
char choice;
pipe(fd);
pid=fork();
if(pid==0)
{
execlp("./draw.out", "draw.out", NULL);
}
else
{
do
{
choice=getch();
close(fd[0]);
write(fd[1],&choice,1);
close(fd[1]);
kill(pid,SIGUSR2);
}while(choice!='q');
}
return 1;
//getchar();
}
第二个程序的代码:
#
include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
typedef struct
{
int x;
int y;
}Point;
typedef struct
{
Point dots[3];
}Tool;
void drawBoard(int array[][20]);
void initBoard(int array[][20]);
Tool retrieveTool();
bool changeLocation(int array[][20],Tool* tool);
void my_handler(int signum);
int main()
{
bool nextTool=true;
Tool temp=retrieveTool();
int gameBoard[20][20];
signal(SIGUSR2, my_handler);
initBoard(gameBoard);
changeLocation(gameBoard,&temp);
drawBoard(gameBoard);
while(true)
{
sleep(1);
system("clear");
if(!changeLocation(gameBoard,&temp))
temp=retrieveTool();
drawBoard(gameBoard);
}
return 1;
//getchar();
}
void my_handler(int signum)
{
char geth='a';
if (signum == SIGUSR2)
{
close(fd[1]);
read(fd[0],&geth,1);
close(fd[0]);
printf("Received SIGUSR2!%c\n",geth);
}
}
正如您在第一个程序中看到的,我将fd [2]变量定义为管道,并且我将用户的char发送到管道。 我希望另一个程序中的信号处理程序“my_handler”将从同一个管道中读取,但是这里没有定义fd(在第二个程序中)。
我该怎么做?
答案 0 :(得分:1)
虽然管道变量fd仅在父级中,但实际的文件描述符是共享的。只要程序知道它们是什么(作为整数),就可以使用它们。所以有几个选项
将描述符编号传递给exec调用中的子程序(类似
)sprintf(buf1,“%d”,fd [0]);
execlp(“./ draw.out”,“draw.out”,“ - in”,buf1,NULL);
然后在draw中读取argv中的描述符。
第二个相当常见的选项是使用输入fd 0并输出fd 1的约定。这仅适用于您的子程序不使用stdin(或std :: cin)的情况。否则你可以选择另一个你确定可用的描述符(这比它听起来更难)。为此,您需要在fork之后但在exec之前复制描述符。像
这样的东西DUP2(FD [0],0);
接近(FD [0]);
接近(FD [1]); //孩子不需要fd [1]
execlp(....)
在所有情况下,您都需要确保关闭任何未使用的描述符(包括旧副本)。我建议尽快进行近距离调用(在fork之后的每个块的开头)。否则,程序将不会在描述符上遇到EOF。顺便说一句,你的程序都在循环或处理程序中关闭描述符,这些描述符可以被多次调用 - 两者都不可能是正确的。您应该检查读取,写入和关闭的返回值,以帮助调试。