zoukankan      html  css  js  c++  java
  • Linux IPC(Inter-Process Communication,进程间通信)之管道学习

    1.标准流管道

    管道操作支持文件流模式,用来创建链接还有一个进程的管道,通过函数popen和pclose
    popen的详细介绍在本blog:Linux 多进程学习中有具体介绍

    2.无名管道(PIPE)

    特点:
    1)仅仅能在亲缘关系进程间通信(父子或兄弟)
    2)半双工(固定的读端和固定的写端)
    3)是特殊文件,能够用read,write等,在内存中
    管道函数原型:
    #include<unistd.h>
    int pipe(int fds[2]);
    管道在程序中用一对文件描写叙述符表示,一个是可读属性,一个是可写属性:fds[0]读,fds[1]写
    两个进程必须有继承关系,才干继承这对打开的文件描写叙述符

    int main(){
    	int fds[2];
    	if(pipe(fds)==-1){
    		perror("pipe:");
    		return 0;
    	}
    	char buf[1024]="";
    	if(fork()==0){
    		close(fds[1]);
    		while(memset(buf,0,sizeof(buf))){
    			if(read(fds[0],buf,1024)==0){//当管道里没有数据的时候就退出
    				break;
    			}
    			printf("child:read:");
    			puts(buf);
    		}
    		exit(1);
    	}
    	else{
    		close(fds[0]);
    //		char p[1024];
    //		char *p="Hello world!";
    	while(memset(buf,0,1024),fgets(buf,1024,stdin)!=NULL)
    			write(fds[1],buf,1024);
    		close(fds[1]);
    		printf("parents,finish
    ");
    		wait(NULL);//wait一定要放在close的后面,由于仅仅有先将父进程的fds[1]关掉,当子进程没有数据读的时候才会退出,否则会导致死锁
    	}
    }

    3命名管道(FIFO)

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

    3.1创建,删除FIFO文件

    创建FIFO文件与创建普通文件非常类似,仅仅是创建之后的文件FIFO
    创建FIFO文件的函数原型
    #include<sys/types.h>
    #include<sys/stat.h>
    int mkfifo(const char *pathname,mode_t mode);
    參数pathname为要创建的FIFO文件的全路径名;
    參数mode为文件的訪问权限
    创建成功返回0,创建失败为-1
    删除FIFO文件的函数原型为
    int unlink(const char *pathname);
    样例:
    #include<iostream>
    using namespace std;
    int main(int argc,char *argv[]){
    	if(mkfifo(argv[1],0666)==-1){
    		perror("ew");
    		return 0;
    	}
    	unlink(argv[1]);
    }

    3.2打开,关闭FIFO文件

    对于FIFO类型的文件的打开/关闭更普通文件一样,都是用open和close函数。用O_WRONLY打开FIFO的写入端,用O_RDONLY选项,则打开FIFO的读入端,写入读入端都能够被几个进程同一时候打开。
    fd_recv=open(argv[1],O_RDONLY);
    fd_send=open(argv[2],O_WRONLY);
    if(fd_send==-1){
    perror("fd_send");
    exit(1);
    }

    3.3读写FIFO

    读:
    fd_recv=open(argv[1],O_RDONLY);
    char buf_recv[1024]="";
    if(read(fd_recv,buf_recv,1024)!=0)   write(1,buf_recv,strlen(buf_recv));
    close (fd_recv)
    写:
    fd_send=open(argv[2],O_WRONLY);
    char buf_send[1024]="";
    if(fgets(buf_send,1024,stdin)!=NULL) write(fp_send,buf_send,strlen(buf_send));
    close(fd_send);
    程序示范:
    pork_send.c与pork_recv.c聊天
    使用fork开辟留一个进程,两个程序能够进行聊天功能

    /*************************************************************************
    	> File Name: pork_send.c
    	> Author: yang
    	> Mail:826123027@qq.com 
    	> Created Time: 2014年08月22日 星期五 19:54:08
     ************************************************************************/
    
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<memory.h>
    int main(int argc,char *argv[]){
    	if(mkfifo(argv[1],0666)==-1){
    		perror("mkfifo1");
    		exit(1);
    	}
    	int fd_send,fd_recv;
    	fd_send=open(argv[1],O_WRONLY);
    	fd_recv=open(argv[2],O_RDONLY);
    	char buf_recv[1024]="";
    	char buf_send[1024]="";
    	printf("opening!
    ");
    	if(fork()==0){//开皮一个进程,用来接受信息
    		close(fd_send);
    		while(memset(buf_recv,0,sizeof(buf_recv)),read(fd_recv,buf_recv,1024)>0){
    			write(1,buf_recv,strlen(buf_recv));
    		}
    		close(fd_recv);
    		exit(1);
    	}
    	close(fd_recv);
    	while(memset(buf_send,0,sizeof(buf_send)),fgets(buf_send,1024,stdin)!=NULL){
    		write(fd_send,buf_send,strlen(buf_send));//用来发送信息
    	}
    	close(fd_send);
    	wait(NULL);
    }

    /*************************************************************************
    	> File Name: pork_recv.c
    	> Author: yang
    	> Mail:826123027@qq.com 
    	> Created Time: 2014年08月22日 星期五 20:12:32
     ************************************************************************/
    
    #include<string.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<memory.h>
    #include<stdio.h>
    int main(int argc,char *argv[]){
    	if(mkfifo(argv[2],0666)==-1){
    		perror("mkfifo2");
    		exit(1);
    	}
    	int fd_send,fd_recv;
    	fd_recv=open(argv[1],O_RDONLY);//注意这里与上面程序的这个位置有所不一样
    	fd_send=open(argv[2],O_WRONLY);
    	char buf_recv[1024]="";
    	char buf_send[1024]="";
    	printf("opening!
    ");
    	if(fork()==0){//接受信息
    		close(fd_send);
    		while(memset(buf_recv,0,sizeof(buf_recv)),read(fd_recv,buf_recv,1024)>0){
    			write(1,buf_recv,strlen(buf_recv));
    		}
    		close(fd_recv);
    		exit(1);
    	}
    	close(fd_recv);//发送信息
    	while(memset(buf_send,0,sizeof(buf_send)),fgets(buf_send,1024,stdin)!=NULL){
    		write(fd_send,buf_send,strlen(buf_send));
    	}
    	close(fd_send);
    	wait(NULL);
    }
    







  • 相关阅读:
    想要在控件里面使用触发器,只需要将下面代码填入控件中间即可
    WPF有关控件和模板样式设计的微软官方文档
    XDG0062 XAML 与XDG0008 XAML 错误的解决办法
    在WPF中一种较好的绑定Enums数据方法
    FrameworkElementFactory中的SetBinding与SetValue
    线性表结构:栈
    关于链表的一些问题
    使用Mybatis-Plus的一个坑
    双向链表和双向循环链表
    上下文切换的确切含义了解下
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4090478.html
Copyright © 2011-2022 走看看