22、高级进程间通信

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节点。传送文件描述符使不同进程的文件描述符(不一定相同)执行相同的文件表项。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值