基于信号量的进程间通信,基于命名管道与信号的进程间通信

目录

第1关:信号量IPC操作考查

任务描述

相关知识

基于信号量的进程间通信

编程要求

答案:

 第1关:命名管道与信号IPC操作考查

任务描述

相关知识

命名管道通信过程

编程思路

答案:


第1关:信号量IPC操作考查

任务描述

本关任务:编写小程序使用信号量实现进程间通信,理解信号量是主要用来实现进程间同步,避免并发访问共享资源。

相关知识

为了完成本关任务,你需要掌握:信号量的相关通信过程。

基于信号量的进程间通信

1)信号量集合数据结构 规定了信号量的权限、指针、最近修改时间和队列中信号量的队列信息。

2) 单信号量结构

struct sem
{
   int semval;//信号量的值
   int sempid;//最近一个操作的进程号PID
} 

3)创建信号量集合

int semget(key_t key,int _nsems,int _semflg)
     key 由ftok创建
     nsems为创建的信号量个数,以数组方式存储
     semflg标识信号量集合的权限,最终权限属于当前进程
     umask值与设置的perm值,即perm&~umask,也可以如下:
          IPC_CREAT:如果key不存在,创建
          IPC_EXCL:如果key存在,返回失败
          IPC_NOWAIT:如果需要等待返回失败

4)控制信号量集合、信号量

semctl(int semid,int semnum,int cmd,...);
    semid要操作的信号量集合
    semnum集合中信号量的编号
    cmd执行的操作
         ipc头文件中
         IPC_RMID删除
         IPC_SET设置ipc_perm参数
         IPC_STAT获取ipc_perm参数
         IPC_INFO获取系统信息 

自定义

#define GETPID  获取信号量拥有者的pid
#define GETVAL  获取信号量的值返回信号的值
#define GETALL  获取所有信号量的值
#define GETNCNT 获取等待信号量的值递增的进程数
#define GETZCNT获取等待信号量的值递减的进程数
#define SETVAL 设置信号量的值,设置值在第四个参数中
#define SETALL 设置所有信号量的值

编程要求

根据提示,在右侧编辑器补充代码,了解OpenEuler系统如何使用信号量进行IPC通信,代码中先用sem_read_array[]数组存储数据,并进行信号量与数据的输出,我们需要补充代码使用semctl函数输出一样的数据。

答案:
#include <errno.h>
 #define MAX_SEMAPHORES  5
#include <stdio.h>
 #include <sys/types.h>
 #include <sys/sem.h>
 #include <errno.h>
 #define MAX_SEMAPHORES  5
 int main(int argc,char *argv[])
{
    int i, ret, semid;
    unsigned short sem_array[MAX_SEMAPHORES];
    unsigned short sem_read_array[MAX_SEMAPHORES];

    union semun
    {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
    } arg;
    semid = semget( IPC_PRIVATE, MAX_SEMAPHORES,IPC_CREAT | 0666 );

    if (semid != -1)

    {
        for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
        {
            sem_array[i] = (unsigned short)(i+1);
        }
        arg.array = sem_array;
        ret = semctl( semid, 0, SETALL, arg);
        if (ret == -1) 
            printf("SETALL failed (%d)\n", errno);
        arg.array = sem_read_array;
        ret = semctl( semid, 0, GETALL, arg );
        if (ret == -1) 
            printf("GETALL failed (%d)\n", errno);
        for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
        {
           printf("Semaphore %d, value %d\n", i, sem_read_array[i] );

        }
        for ( i = 0 ; i < MAX_SEMAPHORES ; i++ )
        {
            /*请调用semctl函数,读取并输出与上述数组输出相同的输出*/
            ret = semctl(semid, i, GETVAL);
            if (ret == -1) {
                printf("GETVAL failed for semaphore %d (%d)\n", i, errno);
            } else {
                printf("Semaphore %d, value %d\n", i, ret);
            }
        }
        ret = semctl( semid, 0, IPC_RMID );
    }
    else
        printf("Could not allocate semaphore (%d)\n", errno);
    return 0;
}

 第1关:命名管道与信号IPC操作考查

任务描述

本关任务:编写小程序,先创建命名管道,子进程以读的方式打开,父进程以写的方式打开,查看相关输出。

相关知识

为了完成本关任务,你需要掌握:命名管道的的相关通信过程。

命名管道通信过程

无名管道是临时的,完成通信就自动消失。

1)必须同时有读和写操作,可以是一个或者多个进程

2)无数据,读堵塞 有数据,小于预读取量,读出所有。 有数据,大于预读取量,读出期望数量。

3)无空间,写堵塞 有空间,小于欲写入量,写满阻塞。 有空间,大于欲写入量,写完返回。 4)中途一个退出操作 写退出,返回SIGPIPE信号。 读退出,读操作不阻塞,直接返回0。

编程思路

根据提示,在右侧编辑器补充代码,使用SIGPIPE信号进行记录,读通道关闭后写通道写入。首先子进程以读的方式打开管道,然后父进程以写的方式打开管道,父进程当即睡眠1秒,子进程关闭读管道,当父进程休眠完成后开始写入,会发出写入失败信号。

答案:
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/types.h>

void handler(int sig)
{
    printf("sig=%d\n",sig);

}
int main(void)
{
    int j;
    signal(SIGPIPE,handler);//在reader中止之后写Pipe的时候发送
    unlink("FIFO");
    mkfifo("FIFO",0644);
    pid_t pid;
    pid=fork();
    if (pid == 0) {
        /*子进程打开读管道,随后关闭管道*/
        int fd = open("FIFO", O_RDONLY);
        close(fd);
    } else {
        /*父进程打开写通道,休眠1秒,尝试写入*/
        int fd = open("FIFO", O_WRONLY);
        sleep(1);
        char buffer[] = "Hello, pipe!";
        int ret = write(fd, buffer, strlen(buffer));
     
        close(fd);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星与星熙.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值