Проблемы и странные впечатления при работе с семафорами System V


Система:

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

Задача:

Я хотел использовать семафор для реализации атомарности процесса

Ниже программа просто записывает некоторые данные в FIFO, в то время как некоторые другие процессы также пытаются записать в тот же FIFO, но процесс ниже, который получает семафор первым, должен завершить его запись и освободить ключ для другие

заголовок.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 P1n");
 exit(1);
 }
 //2.Semaphore Control
 a.val=1;
 ret= semctl(KK,0,a);
 if(ret==-1)
 {
  perror("SemCtl Error in P1n");
  exit(1);
 }
 //3.Semaphore Operations
 ret=semop(KK,&sops[0],1);
 if(ret==-1)
 {
  perror("Semop Error in decrementing at P1n");
  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 P1n");
  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&

читатель.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 Startedn");
 while(1)
 {
 if( (ret=read(fd,&request,sizeof(request))) == -1)
 {
  perror("Read in Server Failedn");
  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 Completen");
}

в соответствии с моей целью я хочу, чтобы результат был таким

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 
Я думаю, что мне удалось ясно объяснить свою проблему. любое дальнейшее редактирование приветствуется
2 3

2 ответа:

Ошибка кроется здесь, в коде

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

Где я поместил его во все три процесса, где они были репликами друг к другу, когда process2, содержащий тот же код, начал выполнять семафор, который декрементируется process1, уже снова инициализируется, что нарушило атомарность 3 процессов

Мне нужно было сделать 3 исправления для запуска кода:

1) вам это может не понадобиться, так как у вас, вероятно, есть процесс, который читает очередь. Но так как у меня был только ваш "процесс".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);