单进程中的管道:
int fd[2]
注:单进程中的管道无实际用处,管道用于多进程间通信。
main1.c
一个进程实现管道通信(管道主要用于多进程通信)
#include
#include
#include
int main(void)
{
int fd[2];
int ret;
char buff1[1024];
char buff2[1024];
// fd为长度为2类型为int的数组,用于保存读管道和写管道两个文件描述符
ret = pipe(fd);
if (ret !=0) {
printf("create pipe failed!\n");
exit(1);
}
// 往管道中写入数据
strcpy(buff1, "Hello!");
write(fd[1], buff1, strlen(buff1));
printf("send information:%s\n", buff1);
// 往管道中读出数据
bzero(buff2, sizeof(buff2));
read(fd[0], buff2, sizeof(buff2));
printf("received information:%s\n", buff2);
return 0;
}
父子进程通过管道通信步骤
#include
#include
#include
int main(void)
{
int fd[2];
int ret;
char buff1[1024];
char buff2[1024];
pid_t pd;
ret = pipe(fd);
if (ret !=0) {
printf("create pipe failed!\n");
exit(1);
}
pd = fork();
if (pd == -1) {
printf("fork error!\n");
exit(1);
} else if (pd == 0) {
bzero(buff2, sizeof(buff2));
read(fd[0], buff2, sizeof(buff2));
printf("process(%d) received information:%s\n", getpid(), buff2);
} else {
strcpy(buff1, "Hello!");
write(fd[1], buff1, strlen(buff1));
printf("process(%d) send information:%s\n", getpid(), buff1);
}
if (pd > 0) {
wait();
}
return 0;
}
问题:
解决方案:
实际实现方式:
父子进程各有一个管道的读端和写端;
#include
#include
#include
int main(void)
{
int fd[2];
int ret;
char buff1[1024];
char buff2[1024];
pid_t pd;
ret = pipe(fd);
if (ret !=0) {
printf("create pipe failed!\n");
exit(1);
}
pd = fork();
if (pd == -1) {
printf("fork error!\n");
exit(1);
} else if (pd == 0) {
close(fd[1]);// 子进程把写段关闭
bzero(buff2, sizeof(buff2));
read(fd[0], buff2, sizeof(buff2));
printf("process(%d) received information:%s\n", getpid(), buff2);
} else {
strcpy(buff1, "Hello!");
close (fd[0]);
write(fd[1], buff1, strlen(buff1));
printf("process(%d) send information:%s\n", getpid(), buff1);
close (fd[1]);
}
if (pd > 0) {
wait();
}
return 0;
}
解决方案:
#include
#include
#include
#include
int main(void)
{
int fd[2];
int ret;
char buff1[1024];
char buff2[1024];
pid_t pd;
ret = pipe(fd);
if (ret != 0) {
printf("create pipe failed!\n");
exit(1);
}
pd = fork();
if (pd == -1) {
printf("fork error!\n");
exit(1);
}
else if (pd == 0) {
//bzero(buff2, sizeof(buff2));
sprintf(buff2, "%d", fd[0]);
/*前两个都是要执行的程序名
execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针
所指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:
argv[0],argv[1]... 最后一个参数须用空指针NULL作结束*/
execl("main3_2", "main3_2", buff2, 0);// 子进程执行main3_2
printf("execl error!\n");
exit(1);
}
else {
strcpy(buff1, "Hello!");
write(fd[1], buff1, strlen(buff1));
printf("process(%d) send information:%s\n", getpid(), buff1);
}
if (pd > 0) {
wait();
}
return 0;
}
main3_2.c
#include
#include
#include
#include
int main(int argc, char* argv[])
{
int fd;
char buff[1024] = {0};
sscanf(argv[1], "%d", &fd);// 获取管道读端句柄
read(fd, buff, sizeof(buff));
printf("Process(%d) received information:%s\n", getpid(), buff);
return 0;
}
popen的作用:
用来在两个程序之间传递数据:
在程序A中使用popen调用程序B时,有两种用法:
// 返回值:成功,返回FILE* 失败, 返回空
FILE * popen( const char * command,const char * type);
读取 ls -l
的结果
main7.c
#include
#include
#define BUFF_SIZE 1024
int main(void)
{
FILE * file;
char buff[BUFF_SIZE+1];
int cnt;
// system("ls -l > result.txt");
file = popen("ls -l", "r"); // 读出ls -l 输出的结果
if (!file) {
printf("fopen failed!\n");
exit(1);
}
cnt = fread(buff, sizeof(char), BUFF_SIZE, file);
if (cnt > 0) {
buff[cnt] = '\0';
printf("%s", buff);
}
pclose(file);
return 0;
}
输出一个字符串,到p2程序中
#include
#include
#include
#define BUFF_SIZE 1024
int main(void)
{
FILE * file;
char buff[BUFF_SIZE+1];
int cnt;
file = popen("./p2", "w");
if (!file) {
printf("fopen failed!\n");
exit(1);
}
strcpy(buff, "hello world! I`m martin");
cnt = fwrite(buff, sizeof(char), strlen(buff), file);
pclose(file);
return 0;
}
popen的优缺点:
如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE