管道-进程通信

3种类型:1、标准流管道  2、无名管道  3、命名管道(pipe)

1、标准流管道

      像文件操作有标准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;
}

XJVzwvlUAAC4I7Sv7Enh+W3fZI0LjWM2zvETPtS9o5unrrQ6y7tXu7JOGliRhLXyfJMw2hpkGlLl2edPfMkQAADAlREShzwBAACAARASIzwAAAAAAAAAAAAAAAAAAAAAAAAAAABumP8BDBa4m8LU5wMAAAAASUVORK5CYII=

//另外一个进程是命令
AbK9Hb6dYbonAAAAAElFTkSuQmCC
#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;
}
RAqQ8AAAAAElFTkSuQmCC
#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他是特殊的文件,可以用readwrite等,只能在内存中

管道函数原型:

       #include <unistd.h>

      int pipe(int pipefd[2]);

管道在程序中用一对文件描述符表示,其中一个文件描述符有可读属性,一个有可写的属性。fds[0] 是读,fds[1] 是写。

     函数pipe用于创建一个无名管道,如果成功,fds[0]存放可读的文件描述符,fds[1]存放可写文件描述符,并且函数返回0,否则返回-1

     通过调用pipe获取这对打开的文件描述符后,一个进程就可以从fds[0]中读数据,而另一个进程就可以往fds[1]中写数据。当然两进程间必须有继承关系,才能继承这对打开的文件描述符。

       管道不象真正的物理文件,不是持久的,即两进程终止后,管道也自动消失了。

TWvHQUAcewoKJrOJmOgYbCE2hGhLiqIokrwIIYQQot1QPFcKQgghhBDtxf8HuDMV0B0kOnwAAAAASUVORK5CYII=  //也就是其实就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;
}
wHIBX0iYlBKmAAAAABJRU5ErkJggg==

       管道两端的关闭是有先后顺序的,如果先关闭写端则从另一端读数据时,read函数将返回0,表示管道已经关闭;但是如果先关闭读端,则从另一端写数据时,将会使写数据的进程接收到SIGPIPE信号,如果写进程不对该信号进行处理,将导致写进程终止,如果写进程处理了该信号,则写数据的write函数返回一个负值,表示管道已经关闭







3、命名管道(FIFO)

     无名管道只能在 亲缘关系 的进程间通信大大限制了管道的使用,有名管道突破了这个限制, 通过指定路径名的方式实现不相关进程间的通信

创建FIFO文件的函数原型:

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);


参数pathname为要创建的FIFO文件的全路径名;

参数mode为文件访问权限

如果创建成功,则返回0,否则-1

删除FIFO文件的函数原型为:(其他文件,目录都可以删除)

     #include <unistd.h>

     int 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;
}
UrpABb5RS38AAAAASUVORK5CYII=
#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;
}
PWzpcy79Ja8AAAAASUVORK5CYII=




转载于:https://www.cnblogs.com/meihao1203/p/8477167.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值