像文件操作有标准io流一样,管道也支持文件流模式。用来创建连接到另一进程的管道,是通过函数 popen 和 pclose 。
函数原型:
#include <stdio.h>
FILE* popen(const char* command, const char* open_mode); //两个进程间创建了一个管道,用来进行数据交换;每次就打开一条管道
int pclose(FILE* fp);
函数popen():允许一个程序将另一个程序作为新进程来启动,并可以传递数据给它或者通过它接收数据。command字符串是要运行的程序名。open_mode必须是“r”或“w”。如果open_mode是“r”,被调用程序的输出就可以被调用程序(popen)使用,调用程序利用popen函数返回的FILE*文件流指针,就可以通过常用的stdio库函数(如fread)来读取被调用程序的输出;如果open_mode是“w”,调用程序(popen)就可以用fwrite向被调用程序发送数据,而被调用程序可以在自己的标准输入上读取这些数据
函数pclose():用popen启动的进程结束时,我们可以用pclose函数关闭与之关联的文件流。
printf.c | popen_r.c |
#include<stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
//另外一个进程是命令
|
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("error args\n");
return -1;
}
FILE* fp;
fp=popen(argv[1],"r");
if(NULL==fp)
{
perror("popen");
return -1;
}
char buf[128]={0};
fread(buf,sizeof(char),sizeof(buf),fp);
pclose(fp);
printf("%s\n",buf);
return 0;
}
|
gets.c | popen_w.c |
#include<stdio.h>
int main()
{
char buf[128]={0};
fgets(buf,sizeof(buf),stdin);
printf("%s\n",buf);
return 0;
}
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc,char* argv[])
{
if(argc!=3)
{
printf("error args\n");
return -1;
}
FILE* fp;
fp=popen(argv[1],"w");
if(NULL==fp)
{
perror("popen");
return -1;
}
fwrite(argv[2],sizeof(char),strlen(argv[2]),fp);
pclose(fp);
return 0;
}
|
2、无名管道(PIPE)
管道是linux进程间通信的一种方式,如命令ps -ef | grep ntp
无名管道的特点:
1只能在亲缘关系进程间通信(父子或兄弟)
2半双工(固定的读端和固定的写端)
3他是特殊的文件,可以用read、write等,只能在内存中
管道函数原型:
#include <unistd.h>
int pipe(int pipefd[2]);
管道在程序中用一对文件描述符表示,其中一个文件描述符有可读属性,一个有可写的属性。fds[0] 是读,fds[1] 是写。
函数pipe用于创建一个无名管道,如果成功,fds[0]存放可读的文件描述符,fds[1]存放可写文件描述符,并且函数返回0,否则返回-1。
通过调用pipe获取这对打开的文件描述符后,一个进程就可以从fds[0]中读数据,而另一个进程就可以往fds[1]中写数据。当然两进程间必须有继承关系,才能继承这对打开的文件描述符。
管道不象真正的物理文件,不是持久的,即两进程终止后,管道也自动消失了。
//也就是其实就fds[2]在内核就一条管道
示例:创建父子进程,创建无名管道,父写子读
pipe.c | |
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{
int fds[2]={0};
pipe(fds);
if(!fork())
{
close(fds[1]); //子进程关闭写端
char buf[128]={0};
read(fds[0],buf,sizeof(buf));
printf("buf=%s\n",buf);
close(fds[0]);
exit(0);
}
else
{
close(fds[0]);
write(fds[1],"
Hello",5);
wait(NULL);
close(fds[1]);
exit(0);
}
return 0;
}
|
创建FIFO文件的函数原型:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
参数pathname为要创建的FIFO文件的全路径名;
参数mode为文件访问权限
如果创建成功,则返回0,否则-1int unlink(const char*pathname);
mkfifo.c //创建 | unlink.c |
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
int main()
{
int ret = mkfifo("1.pipe",0666);
if(-1==ret)
{
perror("mkfifo");
return -1;
}
return 0;
}
|
#include<unistd.h>
#include<stdio.h>
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("error args\n");
return -1;
}
int ret = unlink(argv[1]);
if(-1==ret)
{
perror("unlink");
return -1;
}
return 0;
}
|