小工具知识网

当前位置: 首页 > 行业知识 > Linux信号【systemV】

行业知识

Linux信号【systemV】

2026-10-30 04:15:00 来源:互联网转载

���录

前言

正文:

1消息队列

1.1什么是消息队列? 

1.2消息队列的数据结构 

1.3消息队列的相关接口 

1.3.1创建 

1.3.2释放 

1.3.3发送 

1.3.4接收 

1.4消息队列补充

2.信号量 

2.1什么是信号量 

2.2互斥相关概念 

2.3信号量的数据结构

2.4信号量相关接口 

2.4.1创建 

2.4.2释放

2.4.3操作

2.5信号量补充

3.深入理解 System V通信方式 

总结:



前言

在 System V 通信标准中,还有一种通信方式:消息队列,以及一种实现互斥的工具:信号量;随着时代的发展,这些陈旧的标准都已经较少使用了,但作为 IPC 中的经典知识,我们可以对其做一个简单了解,扩展 IPC 的知识栈,尤其是 信号量,可以通过它,为以后多线程学习中 POSIX 信号量的学习做铺垫

正文:

1消息队列

1.1什么是消息队列? 

 消息队列(Message Queuing)是一种比较特殊的通信方式,它不同于管道与共享内存那样借助一块空间进行数据读写,而是 在系统中创建了一个队列,这个队列的节点就是数据块,包含类型和信息

  • 假设现在进程 A、B 想要通过消息队列进行通信,首先创建一个消息队列
  • 然后进程 A 将自己想要发送给进程 B 的信息打包成数据块(其中包括发送方的信息),将数据块添加至消息队列队尾处
  • 进程 B 同样也可以向消息队列中添加数据块,同时也会从消息队列中捕获其他进程的数据块,解析后进行读取,这样就完成了通信

     

     

    遍历消息队列时,存数据块 还是 取数据块 取决于 数据块中的类型 type

    注意: 消息队列跟共享内存一样,是由操作系统创建的,其生命周期不随进程,因此在使用结束后需要删除

    下面有关于消息队列详解的文章

     

    • 《什么是消息队列》
    • 《消息队列详解》

      1.2消息队列的数据结构 

      同属于 System V 标准,消息队列也有属于自己的数据结构

      注:msg 表示 消息队列

      struct msqid_ds{struct ipc_perm msg_perm;/* Ownership and permissions */time_t msg_stime;/* Time of last msgsnd(2) */time_t msg_rtime;/* Time of last msgrcv(2) */time_t msg_ctime;/* Time of last change */unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */msgqnum_t msg_qnum;/* Current number of messages in queue */msglen_t msg_qbytes;/* Maximum number of bytes allowed in queue */pid_t msg_lspid;/* PID of last msgsnd(2) */pid_t msg_lrpid;/* PID of last msgrcv(2) */};

       和 共享内存 一样,其中 struct ipc_perm 中存储了 消息队列的基本信息,具体包含内容如下:

      struct ipc_perm{key_t __key;  /* Key supplied to msgget(2) */uid_t uid;  /* Effective UID of owner */gid_t gid;  /* Effective GID of owner */uid_t cuid;  /* Effective UID of creator */gid_t cgid;  /* Effective GID of creator */unsigned short mode;  /* Permissions */unsigned short __seq; /* Sequence number */};

      可以通过 man msgctl 查看函数使用手册,其中就包含了 消息队列 的数据结构信息

      1.3消息队列的相关接口 

       论标准的重要性,消息队列的大小接口风格与共享内存一致,都是出自 System V 标准

      1.3.1创建 

       使用 msgget 函数创建 消息队列

      #include #include #include int msgget(key_t key, int msgflg);

      关于 msgget 函数

       

      与 共享内存 的 shmget 可以说是十分相似了,关于 ftok 函数计算 key 值,这里就不再阐述,可以在这篇文章中学习 《Linux进程间通信【共享内存】》

      简单使用函数 msgget 创建 消息队列,并使用 ipcs -q 指令查看资源情况

       

      #include #include #include #include using namespace std;int main(){    //创建消息队列    int n = msgget(ftok("./", 668), IPC_CREAT | IPC_EXCL | 0666);    if(n == -1)    {        cerr  0 */    char mtext[1]; /* message data */};

      1.4消息队列补充

       System V 版的 消息队列 使用起来比较麻烦,并且过于陈旧,现在已经较少使用了,所以我们不必对其进行深究,知道个大概就行了,如果实际中真遇到了,再查文档也不迟


      2.信号量 

      2.1什么是信号量 

       信号量(semaphore)一种特殊的工具,主要用于实现 同步和互斥

      信号量 又称 信号灯,是各大高校《操作系统》课程中老师提及的高频知识点,往往伴随着 P、V 操作出现,但大多数老师都只是提及了基本概念,并未对 信号量 的本质及使用场景作出详细讲解

      在正式学习 信号量 相关知识前,需要先简单了解下 互斥相关四个概念,为后续 多线程中信号量的学习作铺垫(重点)

      2.2互斥相关概念 

      1、并发 是指系统中同时存在多个独立的活动单元

      • 比如在多线程中,多个执行流可以同时执行代码,可能访问同一份共享资源

        2、互斥 是指同一时刻只允许一个活动单元使用共享资源

        • 即在任何一个时刻,都只允许一个执行流进行共享资源的访问(可以通过加锁实现)

          3、临界资源 与 临界区,多执行流环境中的共享资源就是 临界资源,涉及 临界资源 操作的代码区间即 临界区

          • 在多线程环境中,全局变量就是 临界资源,对全局变量的修改、访问代码属于 临界区

            4、原子性:只允许存在 成功 和 失败 两种状态

            • 比如对变量的修改,要么修改成功,要么修改失败,不会存在修改一半被切走的状态

               所以 互斥 是为了解决 临界资源 在多执行流环境中的并发访问问题,需要借助 互斥锁 或 信号量 等工具实现 原子操作,实现 互斥

               

               

              关于互斥锁(mutex) 的相关知识在 多线程 中介绍,现在先来学习 信号量,搞清楚它是如何实现 互斥 的

              2.3信号量的数据结构

               下面来看看 信号量 的数据结构,通过 man semctl 进行查看

               sem 表示 信号量

              struct semid_ds{    struct ipc_perm sem_perm; /* Ownership and permissions */    time_t sem_otime;         /* Last semop time */    time_t sem_ctime;         /* Last change time */    unsigned long sem_nsems;  /* No. of semaphores in set */};

              System V 家族基本规矩,struct ipc_perm 中存储了 信号量的基本信息,具体包含内容如下:

               

              struct ipc_perm{    key_t __key;          /* Key supplied to semget(2) */    uid_t uid;            /* Effective UID of owner */    gid_t gid;            /* Effective GID of owner */    uid_t cuid;           /* Effective UID of creator */    gid_t cgid;           /* Effective GID of creator */    unsigned short mode;  /* Permissions */    unsigned short __seq; /* Sequence number */};

               显然,无论是 共享内存、消息队列、信号量,它们的 ipc_perm 结构体中的内容都是一模一样的,结构上的统一可以带来管理上的便利,具体原因可以接着往下看

              2.4信号量相关接口 

              2.4.1创建 

               信号量的申请比较特殊,一次可以申请多个信息量,官方称此为 信号量集,所使用函数为 semget

               

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

              关于 semget 函数

              除了参数2,其他基本与另外俩兄弟一模一样,实际传递时,一般传 1,表示只创建一个 信号量

              使用函数创建 信号量集,并通过指令 ipcs -s 查看创建的 信号量集 信息

              #include #include #include #include using namespace std;int main(){    //创建一个信号量    int n = semget(ftok("./", 668), 1, IPC_CREAT | IPC_EXCL | 0666);    if(n == -1)    {        cerr 

上一篇:服务器代理ip费用怎么算?

下一篇:怎么检查主机电源是否通电