• LINUX C系统编程学习笔记进程通信(三)


    消息队列

    一.IPC通讯 

    #include <sys/types.h>

    #include <sys/ipc.h>

    key_t ftok(char *pathname,char proj);

    功能:返回文件对应的键值。

    pathname:文件名

    proj:项目名(不为0即可)

    二.打开/创建消息队列

    #include <sys/msg.h>

    int msgget(key_t key,int msgflg);

    功能:返回与键值key相对应的消息队列描述字 

    key:键值,由ftok获得。

    msgflg:标志位 。

    标志位的取值:

    IPC_CREAT 创建新的消息队列。

    IPC_EXCL 与IPC_CREAT一同使用,表示如果要穿件的消息队列已存在,则返回错误。

    IPC_NOWAIT 读写消息队列要求无法得到满足时,不阻塞。 

    以下两种情况下,将创建一个新的消息队列。

    1.如果没有与键值key相对应的消息队列,并且msgflg中包含了IPC_CREAT标志位。

    2.key参数为IPC_PRIVATE 

    创建消息队列: 

    int open_queue(key_t keyval)
    {
        int qid;
        if ((qid = msgget(keyval,IPC_CREAT)) == -1)
        {
            return -1;
        }
        return qid;


    发送消息

    int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg);

    功能:向消息队列发送一条消息。

    msqid:消息队列描述符。

    msgp:消息结构指针。

    msgsz:消息大小。

    msgflg:发送消息的标志。

    消息格式:

    struct msgbuf

    {
        long mtype;   //消息类型 > 0
        char mtext[0];//消息数据的首地址

    }; 


    接收消息

    int msmrcv(int msqid,struct msgbuf *msgp,int msgsz,,long msgtyp,int msgflg) 

    功能:从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msg指向的msgbuf结构中

    成功读取消息以后,队列中的这条信息将删除。

    简单的例子:

    int read_message(int qid,long type,struct mymsgbuf *qbuf)
    {
        int result,length;
        length = sizeof(struct mymsgbuf) - sizeof(long);
        if ((result = msgrcv(qid,qbuf,length,type,0)) == -1)
        {
            return -1;
        }
        return result;

    综合实例:

    #include <stdio.h>
    #include <sys/msg.h>
    #include <sys/types.h>
    #include <sys/types.h>
    #include <sys/ipc.h>

    struct msg_buf
    {
        int mtype;
        char data[255];
    }
    int main()
    {
        key_t key;
        int msgid;
        int ret;
        struct msg_buf msgbuf;
        key = ftok("/tmp/2",'a');
        printf("key = [%s]\n",key);
        msgid = msgget(key,IPC_CREAT|0666);  //创建一个消息队列
        if (msgid == -1)
        {
            printf("Creat error\n");
            return -1;
        }
        msgbuf.mtype = getpid(); //获得进程ID
        strcpy(msgbuf.data,"test haha");
        ret = msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);//发送信息
        if (ret == -1)
        {
            printf("send message error\n");
            return -1;
        }
        memset(&msgbuf,0,sizeof(msgbuf));
        ret = msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);//接受信息
        if (ret == -1)
        {
            printf("recv message error\n");
            return -1;
        }
        printf("recv msg = [%s]\n",msgbuf.data);

    信号量

    进程可以根据它判定要否能够访问某些共享资源,还可用于进程同步。

    分类:

    1.二值信号量:值只能取0或1,信号灯强调共享资源,只要共享资源可用,其他进程同样可修改信号灯的值,

    互斥锁:强调进程,占用资源的进程使用资源后,必须由进程本身来解锁。 

    2.计数信号量:信号灯的值,可以取任意非负值。

    创建/打开

    #include <sys/types.h>

    #include  <sys/ipc.h>

    #include <sys/sem.h>

    int semget(key_t key,int nsems,int semflg);

    key:键值,由ftok获得

    nsems:指定打开或者新创建的信号灯集中将包含信号灯的数目。

    semflg:标识,同消息队列 

     

    对信号量控制

    int semop(int semid,struct sembuf *sops,unsigned nsops)

    semid:信号量集的ID .

    sops:是一个操作数组,表明要进行什么操作。

    nsops:sops所指向的数组的元素个数。

    struct sembuf

    {

    unsigned short sem_num;//要操作的信号量在信号量集中的编号,第一个信号的编号是0

    short sem_op; //sem_op的值如果为整数,该值会加到现有的信号量值中,通常用于释放信号量,如果为负值,而其绝对值又大于信号的现值操作将会阻塞,直到

    // 信号值大于或等于sem_op的绝对值,通常用于获取信号量,如果sem_op的值为0,则操作将暂时阻塞,知道信号的值变为0。

    short sem_flg; //信号操作标识,有两种。①。IPC_NOWAIT:对信号的操作不能满足时,sem_op不会阻塞并立即返回,同时设定错误信息,

    // ②。IPC_UNDO:程序结束时,释放信号量,这样做的目的在于避免程序在异常情况下结束时,未将锁定的资源解锁,造成资源永久锁定。 

    }

    ----------------------------------------------在穷无非讨饭,不死终会出头。
  • 相关阅读:
    浏览器渲染原理
    React Router
    链式 add 函数
    函数防抖和函数节流
    242. 有效的字母异位词
    faker 生成模拟数据
    A 第五课 二叉树与图
    使用递归解决问题
    A 第四课 递归_回溯_分治
    A 第三课 贪心算法
  • 原文地址:https://www.cnblogs.com/scrat/p/2568658.html
Copyright © 2020-2023  润新知