[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\n";
    write(fd,message,sizeof(message));
}

int main(int argc,char* argv[],char **environ )
{

    int fd[2];
    if(pipe(fd)){
        printf("cannot create pipe\n");
    }

    pid_t id;
    id=fork();
    //id=vfork();
    switch(id){
        case 0:
            close(fd[1]);
            read_pipe(fd[0]);
            printf("read pipe finished\n");
            break;
        case -1:
            printf("fork failed\n");
            break;
        default:
            close(fd[0]);
            sleep(5);
            write_pipe(fd[1]);
            printf("write pipe finished\n");
            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\n");
    }

    //build msg queue
    if((qid=msgget(msgkey,IPC_CREAT|0660))==-1){
        printf("error\n");
    }

    mymsgbuf.msgtype=3;
    strcpy(mymsgbuf.string_buf,"hello thsi is my msg hehe\n");
    msglen=sizeof(struct msgbuf)-4;

    //send msg 
    /*if(msgsnd(qid,&mymsgbuf,msglen,0)==-1){
        printf("error\n");
    }*/

    //send msg 
    if(msgrcv(qid,&mymsgbuf,msglen,3,0)==-1){
        printf("error\n");
    }

    printf("%s\n",mymsgbuf.string_buf);

    return 0;
}

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

posted @ 2013-07-02 16:06  iyjhabc  阅读(257)  评论(0编辑  收藏  举报