#include
FILE* popen(const char* command, const char* open_ mode);
int pclose(FILE* fp);
//读取当前目录下file的内容
#include
int main()
{FILE* fp = open("./file","r");char buf[128] = {0};while(fgets(buf,sizeof(buf),fp)){puts(buf);}pclose(fp);return 0;
}
//写一串字符串到标准管道流,统计buf单词数量(被调用程序必须阻塞等待标准输入)
#include
int main()
{char buf[128] = {"apple orign banana man fale"};FILE* fp = popen("wc -w","w");//wc -w功能是统计字符串中单词的个数fwrite(buf,sizeof(buf),1,fp);//向被调用的wc -w命令所启动的程序发送buf内容pclose(fp);return 0;
}
管道通信是linux进程通信的一种方式,例如可以使用ps -elf|grep ntp查询和ntp相关的管道
无名管道的特点:
#include
int pipe(int fds[2]);

//创建父子进程,创建无名管道,父进程写数据,子进程读数据
#include
#include
#include
#include
#include
#include int main()
{ int fds[2]; //设置读和写两个文件描述符pipe(fds); //使用pipe函数创建进程,并且将两个文件描述符传入参数printf("fds[0] = %d,fds[1] = %d\n",fds[0],fds[1]);char buf[32] = {'\0'};if(fork() == 0){ //表示子进程close(fds[1]); //子进程关闭写操作sleep(2); //确保父进程有时间关闭读操作,并且向管道中写内容if(read(fds[0],buf,sizeof(buf))){ //将管道中的内容读到buf缓冲区中puts(buf);close(fds[0]); //关闭子进程的读端exit(0); //结束子进程}}else{ //表示父进程close(fds[0]); //父进程关闭读write(fds[1],"hello",6); //从fds[1]向管道中写入hellowaitpid(-1,NULL,0); //等待子进程关闭//wait(NULL); //和waitpid同等效果//write(fds[1],"world",6); //此时会出现断开的管道因为子进程的读已经关闭了close(fds[1]); //父进程关闭写exit(0);}return 0;
}
#include
#include
#include
#include int main()
{int fds[2];pipe(fds);//注释掉这部分将导致写进程被信号SIGPIPE终止,目的是屏蔽SIGPIPE信号,使进程不被终止sigset_t setSig; //设置信号集sigemptyset(&setSig); //将信号集清空,初始化信号集sigaddset(&setSig,SIGPIPE); //将SIGPIPE信号添加到信号集sigprocmask(SIG_BLOCK,&setSig,NULL); //将setSig信号集中的信号加入信号掩码中,作为新的信号屏蔽字char szBuf[10] = {0};if(fork() == 0){ //子进程close(fds[1]); //子进程关闭写sleep(2); //确保父关闭读的时间,并且写入管道中if(read(fds[0], szBuf, sizeof(szBuf))) //读取管道中的内容puts(szBuf);close(fds[0]); //子进程关闭读}else{close(fds[0]);//父进程关闭读write(fds[1], "hello", 6); //父进程通过fds[1]向管道中写入hellowait(NULL); //等待子进程结束write(fds[1], "world", 6); //子进程已经关闭了,父进程读不到东西了close(fds[1]); //父进程关闭读}return 0;
}
创建FIFO文件的方式和创建普通文件的方式一样,其函数名和 Linux下创建FIFO的命令名一样。
删除FIFO文件和 Linux下命令也一样。
#include
#include
int mkfifo(const char *pathname, mode_t mode); //创建管道文件
int unlink(const char *pathname); //删除管道文件
参数 pathname 为要创建的 FIFO 文件的全路径名;
参数 mode为文件的访问权限
如果创建成功,则返回 0,否则-1。
#include
#include
#include
#include
int main(int argc,char *argv[])//演示通过命令行传递参数
{if(argc != 2){ //检查参数数量puts("Usage: MkFifo.exe {filename}");return -1;}if(mkfifo(argv[1], 0666) == -1){ //创建一个管道文件perror("mkfifo fail");return -2;}//删除管道文件unlink(argv[1]);return 0;
}
还可以使用命令创建和删除FIFO文件使用两个终端完成,必须一边读一边写,否则会卡住。

//客户端代码
#include
#include
#include
#include
#include
#include
#include
#include
//定义客户端数据结构体
typedef struct tagmag
{int client_pid;char my_data[512];
}MSG;int main()
{int server_fifo_fd,client_fifo_fd; //定义客户端管道描述符和用户端管道描述符char client_fifo[256]; //设置客户端缓冲区MSG my_msg; char* pstr;memset(&my_msg,0,sizeof(MSG)); //清空my_msgmkfifo("SERVER_FIFO",0777); //新建一个管道文件,权限是0777server_fifo_fd = open("./SERVER_FIFO",O_RDONLY); //以只读的方式打开管道文件if(server_fifo_fd == -1){ //打开失败的处理perror("server_fifo_fd");exit(-1);}int iret;//读取管道文件不为空的情况,将管道内容读到结构体的my_data中while((iret = read(server_fifo_fd,&my_msg.my_data,sizeof(MSG))>0)){ pstr = my_msg.my_data; printf("%s\n",my_msg.my_data); //打印客户端数据while(*pstr!='\0'){ //将所有字符转为大写字符*pstr = toupper(*pstr);pstr++; }memset(client_fifo,0,256); //清空管道文件sprintf(client_fifo,"CLIENT_FIFO_%d",my_msg.client_pid);//客户端pid格式化写入client_fifo中client_fifo_fd = open(client_fifo,O_WRONLY);//客户端以只写的方式打开client_fifo命名的文件客户管道if(client_fifo_fd == -1){perror("client_fifo_fd");exit(-1);}write(client_fifo_fd,&my_msg,sizeof(MSG)); //将结构体写入管道内容printf("%s\n",my_msg.my_data);printf("OVER!\n");close(client_fifo_fd);}return 0;
}
#include
#include
#include
#include
#include
#include
#include
//定义客户端数据结构体
typedef struct tagmag
{int client_pid;char my_data[512];
}MSG;int main()
{int server_fifo_fd,client_fifo_fd;char client_fifo[256] = {0};sprintf(client_fifo,"CLIENT_FIFO_%d",getpid());//将客户端id写入client_fifo字符串中MSG my_msg;memset(&my_msg,0,sizeof(MSG)); //清空结构体my_msg.client_pid = getpid(); //获取客户端的进程idserver_fifo_fd = open("./SERVER_FIFO_NAME",O_WRONLY); //以只写的方式打开服务端管道文件,并获取文件描述符mkfifo(client_fifo,0777); //以client_fifo的内容,创建属于该进程的管道文件while(1){int n = read(STDIN_FILENO,my_msg.my_data,512);//从标准输入读入字符串到my_datamy_msg.my_data[n] = '\0';write(server_fifo_fd,&my_msg,sizeof(MSG));//将结构体内容写入服务器管道文件中client_fifo_fd = open(client_fifo,O_RDONLY);//以只读的方式打开客户端管道文件,并且获取文件描述符n = read(client_fifo_fd,&my_msg,sizeof(MSG));//将结构体读入客户端管道文件中my_msg.my_data[n] = 0; write(STDOUT_FILENO,my_msg.my_data,strlen(my_msg.my_data));//将my_data内容写入标准输入输出中close(client_fifo_fd);//关闭客户端}unlink(client_fifo);//删除客户端管道文件return 0;
}