写在前面

又到了 一年一度期末课设的时候,距离考试还有12天的时间,此时胡小宁还没有复习(准确的说是学习)之前的课程,所以在这个平平无奇的周二,胡小宁就要开始做课设了!

实验三 Linux 进程间通信

  1. 实验目的

    Linux 系统的进程通信机构(IPC)允许在任意进程间大批量地交换数据,通过本实验,理解熟悉 Linux 支持的消息通信机制。

  2. 实验内容和步骤

    (1)使用系统调用 msgget(),msgsnd(),msgrcv()及 msgctl()编制一长度为 1K 的消息的发送和接收程序。

    • 为了便于操作和观察结果,用一个程序作为“引子”,先后 fork()两个子进程 SERVER和 CLIENT,进行通信。
    • SERVER 端建立一个 key 为 75 的消息队列,等待其他进程发来的消息。当遇到类型为 1 的消息,则作为结束信号,取消该队列,并退出 SERVER。SERVER 每接收到一个消息后显示一句“(server) received”。
    • CLIENT 端使用 key 为 75 的消息队列,先后发送类型从 10 到 1 的消息,然后退出。最后的一个消息,即是 SERVER 端需要的结束信号。CLIENT 每发送一条消息后显示一句“(client)sent”。
    • 父进程在 SERVER 和 CLIENT 均退出后结束。

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/msg.h>
    #include <sys/ipc.h>
    #define MSGKEY 75
    struct msgform
    {
    long mtype;
    char mtext[1030];
    }msg;
    int msgqid,i;
    void CLIENT()
    {
    int i;
    msgqid=msgget(MSGKEY,0777);
    for (i=10;i>=1;i--)
    {
    msg.mtype=i;
    printf("(client) sent \n");
    msgsnd(msgqid,&msg,1024,0);
    }
    exit(0);
    }
    void SERVER()
    {
    msgqid=msgget(MSGKEY,0777|IPC_CREAT);
    do{
    msgrcv(msgqid,&msg,1030,0,0);
    printf("(Server) recieved\n");
    } while(msg.mtype!=1);
    msgctl(msgqid,IPC_RMID,0);
    exit(0);
    }
    void main()
    {
    while((i=fork())==-1);
    if(!i) SERVER();
    while((i=fork())==-1);
    if(!i) CLIENT();
    wait(0);
    wait(0);
    }

    运行效果如下:

    效果

UINX/Linux 系统把信号量、消息队列和共享资源统称为进程间通信资源(IPC resource)。提供给用户的 IPC 资源是通过一组系统调用实现的。

  • 用信号量对进程要访问的临界资源进行保护。

  • 用消息队列在进程间以异步方式发送消息。

  • 用一块预留出的内存区域供进程之间交换数据。

    分析:

    创建 IPC 资源的系统调用有:

  • semget()—获得信号量的 IPC 标识符。

  • msgget()—获得消息队列的 IPC 标识符。

  • shmget()—获得共享内存的 IPC 标识符。

    控制 IPC 资源的系统调用有:

  • semctl()—对信号量资源进行控制的函数。

  • msgctl()—对消息队列进行控制的函数。

  • shmctl()—对共享内存进行控制的函数。

    上述函数为获得和设置资源的状态信息提供了一些命令。例如:

  • IPC_SET 命令:设置属主的用户标识符和组标识符。

  • IPC_STAT 和 IPC_INFO 命令:获得资源状态信息。

  • IPC_RMID 命令:释放这个资源。

    操作 IPC 资源的系统调用有:

  • semop()—获得或释放一个 IPC 信号量。 可以实现 P、V 操作

  • msgsnd()—发送一个 IPC 消息。

  • msgrcv()—接收一个 IPC 消息。

  • shmat()—将一个 IPC 共享内存段添加到进程的地址空间

  • shmdt()——将 IPC 共享内存段从私有的地址空间剥离。

    message的传送和控制并不保证完全同步,当一个程序不在激活状态的时候,它完全可能继续睡眠,造成上面现象,在多次send message 后才 receive message.这一点有助于理解消息转送的实现机理。

    (2)观察参考程序,说明控制消息队列系统调用 msgctl()在此起什么作用?

    在此调用msgctl是用于删除id的消息队列。