【问题标题】:Challenges & Strange Experiences while Working with System V Semaphores使用 System V 信号量时的挑战和奇怪的经历
【发布时间】:2014-08-25 08:09:50
【问题描述】:

系统:

Linux ubuntu 3.2.0-57-generic-pae i686 GNU/Linux

问题:

我想利用信号量来实现进程原子性

下面的程序只是将一些数据写入 FIFO,而其他一些进程也尝试写入同一个 FIFO,但下面首先获取信号量的进程必须完成其写入并为其他进程释放密钥

header.h

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
//#include<sys/ipc.h>
//#include<sys/sem.h>
#include<fcntl.h>
#define RES_FIFO 1234
#include<linux/sem.h>
typedef struct
{
pid_t   pid;
int     op1;
int     op2;
char    oper;
}MATH;
int result;
int ret;

流程:

#include"header.h"
int
main(void)
{
 MATH request;
 int fd,KK;
 if(access("TEMP",F_OK)== -1)
    mkfifo("TEMP",0666);
 fd=open("TEMP",O_WRONLY,0666);
 int i=0;
 union semun a;
 struct sembuf sops[2]={{0,-1,SEM_UNDO},{0,1,SEM_UNDO}};
 //1.Semaphore Creation
 KK=semget(RES_FIFO,1,IPC_CREAT);//semaphore set having one semaphore is created and kernel key will be returned
 if(KK==-1)
 {
 perror("Semget Error in P1\n");
 exit(1);
 }
 //2.Semaphore Control
 a.val=1;
 ret= semctl(KK,0,a);
 if(ret==-1)
 {
  perror("SemCtl Error in P1\n");
  exit(1);
 }
 //3.Semaphore Operations
 ret=semop(KK,&sops[0],1);
 if(ret==-1)
 {
  perror("Semop Error in decrementing at P1\n");
  exit(1);
 }


 for(i=0;i<3;i++)
 {
  request.op1=i;
  request.op2=i;
  request.oper='+';
  request.pid=getpid();
  write(fd,&request,sizeof(request));
 // sleep(1);
 }

 ret=semop(KK,&sops[1],2);
 if(ret==-1)
 {
  perror("Semop Error in decrementing at P1\n");
  exit(1);
 }
return 1;
}

但问题是在信号量操作semop 之后,我被卡住了,进程闲置无所事事,进入睡眠状态。那么我的代码有什么问题吗?

最新编辑 1

我已经更新了代码行

ret= semctl(KK,0,SETVAL,a);//command updated as SETVAL

并取消注释该行

sleep(1);

所以我的 process1,process2,process3 有相同的代码,这里我忘了提到从 fifo 读取并在控制台上打印的阅读器代码

所以我在控制台上运行这样的脚本

./reader&
./p1&
./p2&
./p3&

reader.c

#include"header.h"
void
main(void)
{
 MATH request;
 int fd;
 int ret;
 int KK;
 if(access("TEMP",F_OK)== -1)
         mkfifo("TEMP",0666);
 fd=open("TEMP",O_RDONLY,0666);
sleep(3);
printf("Server Read Started\n");
 while(1)
 {
 if( (ret=read(fd,&request,sizeof(request))) == -1)
 {
  perror("Read in Server Failed\n");
  exit(1);
 }
 else if(ret==0)
  continue;
 printf("Read from PID : %d about %d %c %d \n",request.pid,request.op1,request.oper,request.op2);

 }
printf("Read Complete\n");
}

根据我的目标,我希望输出是这样的

Server Read Started
Read from PID : 3673 about 0 + 0 
Read from PID : 3675 about 1 + 1 
Read from PID : 3674 about 2 + 2 
Read from PID : 3673 about 0 - 0 
Read from PID : 3675 about 1 - 1 
Read from PID : 3674 about 2 - 2 
Read from PID : 3673 about 0 * 0 
Read from PID : 3675 about 1 * 1 
Read from PID : 3674 about 2 * 2 

但实际观察到的输出是这样的

Server Read Started
Read from PID : 3673 about 0 + 0 
Read from PID : 3675 about 0 * 0 
Read from PID : 3674 about 0 - 0 
Read from PID : 3673 about 1 + 1 
Read from PID : 3675 about 1 * 1 
Read from PID : 3674 about 1 - 1 
Read from PID : 3673 about 2 + 2 
Read from PID : 3675 about 2 * 2 
Read from PID : 3674 about 2 - 2 

我认为我成功地清楚地解释了我的问题。任何进一步的编辑表示赞赏

【问题讨论】:

    标签: ipc semaphore fifo atomic


    【解决方案1】:

    我需要进行 3 次更正才能运行代码:

    1) 你可能不需要这个,因为你可能有读取队列的进程。但是因为我只有你的“process.c”,所以我需要调整一下:

    fd=open("TEMP",O_WRONLY,0666); -> fd=open("TEMP", O_WRONLY | O_NONBLOCK, 0666);

    2) 这条线似乎有错误,需要调整。要将信号量设置为初始值,您需要使用 SETVAL 进行设置:

    ret=semctl(KK,0,a); -> ret= semctl(KK, 0, SETVAL, a);

    3) 这行似乎有错误。最后一个参数是要抓取多少个操作。它必须是 1:

    ret=semop(KK,&sops[1],2); -> ret=semop(KK,&sops[1],1);

    【讨论】:

      【解决方案2】:

      错误就在代码中

      //2.Semaphore Control
       a.val=1;
       ret= semctl(KK,0,a);
       if(ret==-1)
       {
        perror("SemCtl Error in P1\n");
        exit(1);
       }
      

      我将它放置在所有三个进程中,它们是彼此的副本,当包含相同代码的进程 2 开始执行由进程 1 递减的信号量时,已经再次重新初始化,这破坏了 3 个进程的原子性

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-21
        • 1970-01-01
        • 2017-01-24
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        • 2018-02-06
        相关资源
        最近更新 更多