编写两个独立的程序:reader和writer。利用共享内存和信号,实现数据从writer到reader的妥善传输。

要求:

1、不能重复读取内容,就像管道一样,读过的内容不能再读取。
2、不能覆盖未读取的内容,就像管道一样,未读取的内容不会因为再次写入而遭受破坏。
3、用信号来协调两个程序。

本程序需要用到共享内存和信号完成,通过writer写数据到共享内存,利用信号告诉reader可以读取数据等操作。利用信号告诉对方可以读取数据。

注意:共享内存不能重复创建,防止读写操作由于上一次的操作造成的紊乱,每一次操作完都需要删除再重新

int shmget(key_t key, size_t size, int shmflg);
功能:创建或者打开一个共享内存对象
参数:
key:由 ftok( ) 产生的唯一标识。
size:共享内存的大小,要求是偶数。
shmflg:可选项
IPC_CREAT:创建
IPC_EXCL:如果存在就报错
八进制权限,他们以位或的形式组合起来。
返回值:代表该共享内存的ID
注意:创建的共享内存是物理内存,必须要映射到本进程的内存空间才能使用。

writer.c

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <time.h>

int main()
{

    //1.搞个key:key是ipc的唯一标识
       key_t key = ftok("/mnt/hgfs/share/home/",1);

       // 2,试图新建共享内存
       int id = shmget(key, 100, IPC_CREAT|IPC_EXCL|0666);
       // 如果成功了,要是代表对方还没启动,那么我要负责初始化
       char *addr1;
       if(id == -1 && errno == EEXIST)
       {
            id = shmget(key,100,0666);//初始化
            //将共享内存映射到进程的内存空间
             addr1 = shmat(id,NULL,0);

            if(addr1 == (void *)-1)
            {
                perror("映射内存失败");
                exit(0);
            }
       }
       // 如果成功了,那么代表对方还没启动,那么我要负责初始化
       else if( id > 0)
         {
             printf("对方没启动,我来初始化!\n");

             // 3,将共享内存映射到本进程的内存空间
             addr1 = shmat(id, NULL, 0);
             if(addr1 == (void *)-1)
             {
                 perror("映射内存失败");
                 exit(0);
             }

             bzero(addr1, 100);
         }
       //不断检测判断对方是否已经启动
       while(*(pid_t *)addr1 == 0)
           sleep(1);

       pid_t pids;
       memcpy(&pids , addr1,sizeof (pid_t));
       //收到对方的pid
       printf("reader is pid:%d\n",pids);
       while(1)
       {
           //将要发送的数据放在共享内存中
           fgets(addr1+sizeof(pid_t),100-sizeof(pid_t),stdin);
            //通知对方要可以读数据
           kill(pids,SIGUSR1);
       }
       //解除映射
       shmdt(addr1);

    return 0;
}

reader.c

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <time.h>
char *addr2;
void recv(int sig)
{
    printf("收到的数据:%s",addr2+sizeof (pid_t));
}
int main()
{
	//接受信号,当信号来临时响应recv的函数
    signal(SIGUSR1,recv);

    //1.搞个key
       key_t key = ftok("/mnt/hgfs/share/home/sysprocess/homework/4-1",1);

    // 2,试图新建共享内存
    int id = shmget(key, 100, IPC_CREAT|IPC_EXCL|0666);

    char *addr2;
    // 如果失败了,那么代表对方已经建立了
    if(id == -1 && errno == EEXIST)
    {
        printf("对方已经建立\n");

        id = shmget(key, 100, 0666);

        // 3,将共享内存映射到本进程的内存空间
        addr2 = shmat(id, NULL, 0);
        if(addr2 == (void *)-1)
        {
            perror("映射内存失败");
            exit(0);
        }
    }
     // 如果成功了,那么代表对方还没启动,那么我要负责初始化
      else if(id > 0)
      {
          printf("对方没启动,我来初始化!\n");

          // 3,将共享内存映射到本进程的内存空间
          addr2 = shmat(id, NULL, 0);
          if(addr2 == (void *)-1)
          {
               perror("映射内存失败");
               exit(0);
          }

             bzero(addr2, 100);
         }
   pid_t pid = getpid();

   //把pid以二进制的形式映射到共享内存中
   memcpy(addr2,&pid,sizeof(pid_t));
   printf("reader id pid:%d",pid);
   while(1)
        pause();
   // 5,解除映射
       shmdt(addr2);
    return 0;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咕噜咕噜π

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

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

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

打赏作者

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

抵扣说明:

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

余额充值