zoukankan      html  css  js  c++  java
  • [linux]进程间通信IPC

    LINUX下进程间通信的方式主要有:管道、有名管道、消息队列、信号量、共享内存,此外还有信号和套接字

    管道只能用于亲缘进程(如父子进程)的通信。有名管道可用于非亲缘进程通信。信号量主要用于同步(线程同步与进程同步分别用两组函数操作信号量)。消息队列克服了信号量传递信息少、管道只能传送无类型字节流的弱点。信号类似于软件中断,用于事件通知。共享内存是最快的IPC方式,配合其他方式使用(一般是配合信号量)。

    1、管道

     管道是单向的传输方式,创立管道后系统分配一定大小的缓冲区,数据从输入管道进入缓冲区的头位置,输出管道从管道的未位置取出数据。

    fd[0]为读管道,fd[1]为写管道,读前关闭写管道,写前关闭读管道。fork前必须先创建管道,否则子进程不能继承父进程的文件描述符。

    void read_pipe(int fd){
        char message[100];
        read(fd,message,100);
        printf("from pipe:%s",message);
    }
    
    void write_pipe(int fd){
        char message[]="hello pipe
    ";
        write(fd,message,sizeof(message));
    }
    
    int main(int argc,char* argv[],char **environ )
    {
    
        int fd[2];
        if(pipe(fd)){
            printf("cannot create pipe
    ");
        }
    
        pid_t id;
        id=fork();
        //id=vfork();
        switch(id){
            case 0:
                close(fd[1]);
                read_pipe(fd[0]);
                printf("read pipe finished
    ");
                break;
            case -1:
                printf("fork failed
    ");
                break;
            default:
                close(fd[0]);
                sleep(5);
                write_pipe(fd[1]);
                printf("write pipe finished
    ");
                wait();
        }return 0;
    }

     使用默认的方式创建的管道,read()默认是阻塞的,也就是说,当read()时如管道没数据,则进程阻塞直到管道中有数据。

    2、有名管道

    有名管道提供一个路径名来访问管道,因此可以解决管道只能由亲缘进程访问的缺点。有名管道保证先进先出,又称FIFO。

    3、消息队列

    #include "sys/msg.h"
    
    #define BUF_SIZE 256
    #define PRO_ID 32
    #define PATH "."
    
    int main(int argc,char* argv[],char **environ )
    {
    
        struct msgbuf{
            long msgtype;
            char string_buf[BUF_SIZE];
        }mymsgbuf;
    
        int qid;
        int msglen;
        key_t msgkey;
    
        //get key for msgqueue
        if((msgkey=ftok(PATH,PRO_ID))==-1){
            printf("error
    ");
        }
    
        //build msg queue
        if((qid=msgget(msgkey,IPC_CREAT|0660))==-1){
            printf("error
    ");
        }
    
        mymsgbuf.msgtype=3;
        strcpy(mymsgbuf.string_buf,"hello thsi is my msg hehe
    ");
        msglen=sizeof(struct msgbuf)-4;
    
        //send msg 
        /*if(msgsnd(qid,&mymsgbuf,msglen,0)==-1){
            printf("error
    ");
        }*/
    
        //send msg 
        if(msgrcv(qid,&mymsgbuf,msglen,3,0)==-1){
            printf("error
    ");
        }
    
        printf("%s
    ",mymsgbuf.string_buf);
    
        return 0;
    }

    如消息队列中没有要读的消息,则读进程阻塞直到队列中有要读消息。一旦消息被读取,队列将消除已读消息,也就是说同一消息只能读取一次。

  • 相关阅读:
    php去除数组中重复值,并返回结果!
    SignalR 2 入门
    SignalR支持的平台
    SignalR简介
    作业调度系统quartz.net
    Oracle安装心得
    maven的项目目录解析
    web.xml的<url-parttern>的匹配规则
    Web.xml中四种验证方式
    Web.xml
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/3167192.html
Copyright © 2011-2022 走看看