一个进程间通信问题

freshman_fantom_ywj 2011-12-16 06:01:57
问题起源: A程序 启动一个进程B来运行ping命令(假设), 现在我想把B中ping命令的输出, 返还给A程序.

解决1: A 启动B进程运行ping 命令的代码 改为: ping 192.168.1.1 > ping_output.file
问题: 这样的话, A程序 就得去那个 ping_output.file 里面取输出, 这里最主要问题是 怎么用上面这条命令启动程序, 事实证明用 exec函数来执行 会失败, 因为中间有 ">"重定向, 没有Shell来解析;
最后想了个丑办法 , 将命令写到"ping.sh"里面 再execlp("sh","ping.sh") 这样来运行, 后果就是多开了个sh进程,更不好控制

解决2: 改ping 源码, 将所有输出 dup2(fd, STDOUT_FILENO); fd = open(ping_output.file, O_RDWR); 这样直接将ping所有输出 重定向到 fd (即文件ping_output.file)中
虽然问题好像是解决了, 但是让人蛋疼的是, 往往程序(输出比ping多得多)结束了, 数据还没读完, 结果A程序判断 B程序已经执行完成, 立马结束, 导致数据不完整.

解决3: 突然间想到用管道, 直接通信, 而不老是围着共享文本文件来通信 . 代码如下, 耐心看的朋友应该可以看出问题来
// B程序 使用pipe ,测试程序
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

static int flag = 0;
int main()
{
char output[128] = {0};
int fd[2];
int pid;
int *status;
pipe(fd);

/*为了让下面的READ不阻塞 并判断waitpid*/
int flag = fcntl(fd[0], F_GETFL, 0);
flag |= O_NONBLOCK;
if(fcntl(fd[0], F_SETFL, flag) < 0)
{
perror("fcntl");
return -1;
}

if((pid = fork()) > 0)
{//父进程可以waitpid来等待子进程结束, 所以把读放在父进程里, ping 命令程序放在子进程里
while(1)
{
while(read(fd[0], output, 128) == 128)
if(strlen(output) != 0)
{//这里为了调试 不出现满屏的"parent Process output : "
printf("parent Process output : %s\n", output); //这里调试是输出来,如果是我的程序里,就是把output发送给程序A
memset(output,0, sizeof(output));
}

if(waitpid(pid, status, WNOHANG) == pid)
//if(WIFEXITED(status) !=0 || WIFSIGNALED(status))
{//如果不阻塞方式 等待子进程退出成功, 就退出
printf("----fir = %d -- sec = %d----\n",WIFEXITED(status), WIFSIGNALED(status));
printf("Process parent exit\n");
exit(0);
}
}
}
else
{
//将ping 命令所有输出重定向到 写管道
dup2(fd[1], STDOUT_FILENO);
dup2(fd[1], STDERR_FILENO);

printf("Oh my buf where...\n");
printf("Oh my buf where...\n");
// **** 省略无数个printf...
sleep(5); //问题1: 不管怎么弄, 反正都是等待5秒后 父进程才能读到数据. WHY? 还有优先顺序?
//问题2: 父进程, 根本不按顺序输出, 那A进程怎么接收咯, SHIT
}

return 0;
}



如果有耐心朋友看完了的, 非常感谢~~~!! 知道我有多么可怜了吧! 弄了一天了~ 蛋疼!
...全文
140 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qq120848369 的回复:]

还有,一个popen就解决这个问题了,而且用管道做也是popen的实现,APUE都是源代码.
C/C++ code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

/* no error check at all */
int main(……
[/Quote] 谢谢了! 哈 忘了fork后 关闭相应的pipe了... 明天再去试试!
qq120848369 2011-12-16
  • 打赏
  • 举报
回复
还有,一个popen就解决这个问题了,而且用管道做也是popen的实现,APUE都是源代码.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

/* no error check at all */
int main(int argc, char* argv[])
{
int m_pipe[2];
pid_t pid;

pipe(m_pipe);

if ((pid = fork()) > 0) //parent
{
char ping_out[100];
int nbytes = 0;

close(m_pipe[1]);

while ((nbytes = read(m_pipe[0], ping_out, 100)) != 0)
{
write(STDOUT_FILENO, ping_out, nbytes);
}

close(m_pipe[0]);
wait(NULL);
}
else if (pid == 0) //child
{
dup2(m_pipe[1], STDOUT_FILENO);
dup2(m_pipe[1], STDERR_FILENO);
close(m_pipe[0]);

char command[100];
sprintf(command, "ping -c 4 %s", argv[1]);
execl("/bin/bash", "sh", "-c", command, NULL);
exit(127); //execl error , or never reach here
}
else
{
fprintf(stderr, "fork error\n");
exit(1);
}

return 0;
}

qq120848369 2011-12-16
  • 打赏
  • 举报
回复
哎,楼主扎实点看书吧...

父进程不关闭pipe[1], 子进程跑sh -c ping结束了父进程都读不到EOF.

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧