【Linux计划】XSI IPC

三种IPC这就是所谓的XSI IPC,每间:

  • 消息队列
  • 信号量
  • 共享存储器

以下分别介绍三种IPC的使用方法。

1、消息队列

消息队列是消息的链接表,具有例如以下函数接口:

  • msgget:创建一个新队列或打开一个现存的队列。
  • msgsnd:将消息加入到队列尾端。
  • msgrcv:从队列中取消息。

我们能够自行定义一个表示消息的结构体,它由类型字段和实际数据组成:

struct mest_t {
    long type;          // 消息类型
    char text[512];     // 消息内容
};

有了消息类型。当我们用msgrcv函数取消息时,就不一定要以先进先出的顺序,而是能够依据消息类型取消息了。以下是一段简单的測试代码:

#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>

struct mest_t {
    long type;
    char text[512];
};

int main(void)
{
    pid_t pid;
    int mq_id;
    struct mest_t msg;

    /* IPC_PRIVATE用于创建一个新队列
     * 设置了IPC_EXCL而且设置了IPC_CREAT。当文件存在时返回错误
     */
    mq_id = msgget(IPC_PRIVATE, IPC_CREAT | IPC_EXCL);
    if (mq_id == EEXIST)
        return -1;  /* 返回EEXIST表示IPC已存在 */

    if ((pid = fork()) < 0)
        return -1;
    else if (pid == 0)
    {
        /* 子进程 */
        msg.type = 123;                     /* 消息类型 */
        strcpy(msg.text, "Hello world!");   /* 消息内容 */

        /* 非堵塞方式将消息放入消息队列
         * 队列已满则返回EAGAIN
         */
        while (msgsnd(mq_id, (long *)&msg, 512, IPC_NOWAIT) == EAGAIN)
            sleep(1);
    }
    else
    {
        /* 非堵塞方式从队列中取消息
         * 假设没有指定类型的消息。函数返回-1,errno设置为ENOMSG
         */
        while (msgrcv(mq_id, (long *)&msg, 512, 123, IPC_NOWAIT) == -1)
        {
            if (errno == ENOMSG)
            {
                printf("There is no this type message!\n");
                sleep(1);
            }
        }

        printf("%s\n", msg.text);
    }

    return 0;
}

当父进程须要取的消息类型和子进程发送的消息类型同样时。执行结果例如以下:

父进程可以非常快接收到子进程发送到消息队列中的消息。

可是改动msgrcv的消息类型參数后,执行结果例如以下:

父进程得不到想要的消息,一直打印错误信息。

2、信号量

信号量是一个计数器。用于多进程对共享数据对象的訪问。步骤例如以下:

  • 測试控制该资源的信号量。
  • 若此信号量的值为正。则进程能够使用该资源。进程将信号量值减1,表示它使用了一个资源单位。
  • 若此信号量的值为0。则进程进入休眠状态,直至信号量大于0。进程被唤醒后。它返回至第一步。

当进程不再使用由一个信号量控制的共享资源时,该信号量值增1。假设有进程正在休眠等待此信号量,则唤醒它们。

3、共享存储

共享存储同意多个进程共享一块给定的存储区。是最快的一种IPC。測试代码例如以下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>

#define SHM_SIZE 100
#define SHM_MODE (SHM_W | SHM_R |  IPC_CREAT)

int main()
{
    int shmid;
    char *shmptr;
    pid_t pid;

    /* 获得共享存储标识符 */
    if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)
        return -1;

    if ((pid = fork()) < 0)
        return -1;
    else if (pid == 0)
    {
        shmptr = shmat(shmid, 0, 0);    /* 參数2为0表示由内核分配共享空间 */
        printf("Child attached shared memory is : %lx\n", (unsigned long)shmptr);
        shmdt(shmptr);                  /* 使进程脱离该共享空间 */
    }
    else
    {
        waitpid(pid, NULL, 0);

        shmptr = shmat(shmid, 0, 0);
        printf("Parent attached shared memory is : %lx\n", (unsigned long)shmptr);
        shmdt(shmptr);

        shmctl(shmid, IPC_RMID, 0);  /* 删除该共享存储段 */
    }

    return 0;
}

执行结果:

从上面的实验结果能够看出,父、子进程共享了同一个存储段。

有一点须要注意,shmdt函数仅仅是让进程脱离该共享存储段,但该存储段依旧存在而且shmid依旧有效。它是与shmat相相应的。而还有一个函数shmctl使用IPC_RMID參数时才是真正删除该共享段。

共享存储段和存储映射I/O中的mmap函数很相似,它们之间的差别是:mmap映射的存储段是与文件相关联的,XSI共享存储段则并无这样的关联。

参考:

《unix编程环境》 P415-P432.

时间: 2024-08-05 19:33:47

【Linux计划】XSI IPC的相关文章

【Linux编程】XSI IPC

三种IPC被称作XSI IPC,分别是: 消息队列 信号量 共享存储器 下面分别介绍三种IPC的用法. 1.消息队列 消息队列是消息的链接表,具有如下函数接口: msgget:创建一个新队列或打开一个现存的队列. msgsnd:将消息添加到队列尾端. msgrcv:从队列中取消息. 我们可以自行定义一个表示消息的结构体,它由类型字段和实际数据组成: struct mest_t { long type; // 消息类型 char text[512]; // 消息内容 }; 有了消息类型,当我们用m

进程间通信——XSI IPC之消息队列

进程间通信XSI IPC有3种:消息队列.共享内存.信号量.它们之间有很多相似之处,但也有各自的特殊的地方.消息队列作为其中比较简单的一种,它会有些什么东西呢,来一起探讨探讨.. 消息队列结构 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为是一个类型,接受进程接收的数据块可以有不同的类型值. 我们可以通过发送消息来避免命名管道的同步和阻塞问题. 消息队列与管道不同的是,消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出. 命名管道:

25、Linux计划任务详解

Linux任务计划 相信每个人都有使用闹钟的习惯,比如提醒一次,工作日提醒,女朋友生日提醒(首先你要先有个女朋友),在设定闹钟之后,我们可以在设定的时间去提醒你做什么事情 Linux计划任务工具介绍 在各类系统上面都有计划任务功能,在linux上面主要两种工具,at和crontab at命令是专门来执行处理一次性的任务计划的 crontab可以根据定义的时间周期,循坏的去做一些事情 任务计划分类: 一次性的任务计划:只执行一次就结束 周期性的任务计划:每隔一定时间就去执行 at一次性任务 假如我

第15章 进程间通行 15.6 XSI IPC 15.7 消息队列

15.6 XSI IPC (1)3种称作XSI IPC的IPC是: 1)消息队列 2)信号量 3)共享存储器 (2)标识符和键 1)标识符:是一个非负整数,用于引用IPC结构.是IPC对象的内部名. 2)键:IPC对象的外部名.可使多个合作进程能够在同一IPC对象上汇聚. (3)IPC_PRIVATE键: 用于创建一个新的IPC结构.不能指定此键来引用一个现有的IPC结构. (4)ftok函数: 由一个路径名和项目ID产生一个键. (5)ipc_perm结构体 规定了ipc结构的权限和所有者.

Linux计划任务at&batch&crontab

计划任务        执行一次某任务:at,batch        周期性运行某任务:crontab    1.at命令,只执行一次 at/atq/atrm/batch    at [option]... time        HH:MM[YYYY-mm-dd] //        noon,midnight,teatime //12:00,24:00,16:00        tomorrow HH:MM         now+#            UNIT:minutest,ho

Linux计划任务(转载)

Linux计划任务(转载) Linux的计划任务是系统管理方面的一个重要内容,是系统自动完成工作的一种实现方式,正因为有了计划任务,我们才可以完全实现系统管理的脚本化和自动化. 关于计划任务,Linux根据用户需要提供了两种服务,一种是atd服务,另一种是cron服务 1.atd服务 如果你的计划任务只要执行一次,那么就请你使atd服务.在默认情况下,Linux系统是开启了atd这个服务的.如果不确认你的Linux是否开启了atd服务,请使用下面这个命令查看: # /etc/init.d/atd

linux 计划任务(十)

[教程主题]: 计划任务 [1]at 在windows系统中,windows提供了计划任务这一功能,在控制面板 -< 性能与维护 -< 任务计划, 它的功能就是安排自动运行的任务. 通过'添加任务计划'的一步步引导,则可建立一个定时执行的任务. 在linux系统中你可能已经发现了为什么系统常常会自动的进行一些任务?这些任务到底是谁在支配他们工作的?在linux系统如果你想要让自己设计的备份程序可以自动在某个时间点开始在系统底下运行,而不需要手动来启动它,又该如何处置呢? 这些例行的工作可能又分

深刻理解Linux进程间通信(IPC)

深刻理解Linux进程间通信(IPC) 郑彦兴 原文地址:http://www.ibm.com/developerworks/cn/linux/l-ipc/index.html 一个大型的应用系统,往往需要众多进程协作,进程(Linux进程概念见附1)间通信的重要性显而易见.本系列文章阐述了Linux环境下的几种主要进程间通信手段,并针对每个通信手段关键技术环节给出详细实例.为达到阐明问题的目的,本文还对某些通信手段的内部实现机制进行了分析. 序 linux下的进程通信手段基本上是从Unix平台

linux计划任务自动备份并ftp上传脚本

#!/bin/sh # 备份 #bak_dir=`date +%C%y%m%d%H%M` ##文件命名规则可以是时间 backup_dir=/home/IPTV4.9 ##存储备份文件路径 mkdir -p $backup_dir Ip_addr=`ifconfig \`route |grep default |awk '{print $8}'\` |grep Bcast |awk -F: '{print $2}' |awk '{print $1}'` Host_name=`hostname`