22、高级进程间通信

来源:互联网 发布:windows是操作系统吗 编辑:程序博客网 时间:2024/06/06 14:17

1、UNIX域套接字-在同一计算机系统上运行的两个进程之间传送打开文件描述符。仅仅复制数据不需要执行协议处理。消息队列不能和poll或者select一起使用(只要多个消息队列中一个消息发生)。

//创建一对无命名的、相互连接的UNIX域套接字,可以起到全双工管道的作用int socketpair(int domain, int type, int protocol, int sockfd[2]);

2、

/*服务器创建3个线程,每个线程接受消息,把消息写入套接字多个套接字由poll选择,如果有消息则从该套接字输出消息到终端 */#include "apue.h"#include <poll.h>#include <pthread.h>#include <sys/msg.h>#include <sys/socket.h>#define NQ 3        //队列数量 #define MAXMSZ  512 //消息的最大长度 #define KEY 0x123//为传送给线程的参数定义结构 struct threadinfo{    int qid;    int fd;};//一个消息队列结构 struct mymesg{    long mtype;    char mtext[MAXMSZ];};//线程执行的函数 void helper(void *arg){    int n;    struct mymesg m;    struct threadinfo *tip = arg;    for(;;){        memset(&m, 0, sizeof(m));        //从消息队列接收消息         n = msgrev(tip->qid, &m, MAXMSZ, 0, MSG_NOERROR);        //把消息写到套接字中         write(tip->fd, m.mtext, n);    } }int main(){    int i, n, err;    int fd[2];    int qid[NQ];    struct pollfd pfd[NQ];    struct threadinfo ti[NQ];    pthread_t tid[NQ];    char buf[MAXMSZ];    for(i=0;i<NQ;i++)    {        //创建消息队列,返回队列ID        qid[i]=msgget((KEY+i),IPC_CREAT|0666);        printf("queue ID%d is %d\n",i,qid[i]);        //创建UNIX域套接字        socketpair(AF_UNIX, SOCK_DGRAM, 0, fd);        pfd[i].fd = fd[0];//套接字可读端的一段放在poll中         pfd[i].event = POLLIN;        //封装传给线程的参数        ti[i].qid=qid[i];        ti[i].fd=fd[i];        pthread_create(&tid[i], NULL, helper, &ti[i]);     }    for(;;)    {        poll(pfd, NQ, -1);//如果套接字中都没有消息,则挂起        for(i=0;i<NQ;i++)        {            if(pid[i].revents & POLLIN)//找到有消息的套接字                n=read(pfd[i].fd, buf, sizeof(buf));                buf[n]='\0';                printf("queue id %d, message %s\n", qid[i], buf)         }     }    exit(0);} 

3、

/*客户端向对应消息队列发送消息 */#include "apue.h"#include <sys/msg.h>#define MAXMSZ  512 //消息的最大长度 //一个消息队列结构 struct mymesg{    long mtype;    char mtext[MAXMSZ];};//argv[1]为消息队列对应的key值, argv[2]为要发送的消息 int main(int argc, char *argv[]){    key_t key;    long qid;    size_t nbytes;    struct mymesg m;    key=strtol(argv[1],NULL ,0);//把输入的字符串转化为数值    qid=msgget(key, 0); //根据key值得到对应的消息队列ID    memset(&m, 0, sizeof(m));    strncpy(m.mtext, argv[2],MAXMSZ-1);    nbytes=strlen(m.mtext);    m.mtype=1;    msgsnd(qid, &m, nbytes,0);    exit(0); }

4、命名UNIX域套接字
无关进程不能使用没有名字的套接字。

//struct sockaddr_un即套接字地址(服务地址),bind就是把创建的套接字(返回文件描述符)和这个地址绑定struct sockaddr_un{    sa_family_t sun_family;    char sun_path[108];};

5、传送文件描述符
文件描述符是指向文件表项的指针。当两个进程打开相同文件时,他们文件描述符指向不同的表项,表项指向相同V节点。传送文件描述符使不同进程的文件描述符(不一定相同)执行相同的文件表项。