以超级用户身份运行时工作的信号量无法正常工作

时间:2016-01-05 19:09:25

标签: c linux linux-kernel fork semaphore

我有这个简单的代码,我初始化系统V信号量,所以我的2个进程打印以下代码10次:“abcd”。第一个进程打印“ab”字符串,而另一个进程打印“cd \ n”字符串。 因此,当我以超级用户身份执行它时,一切正常,但是当我没有使用sudo命令执行它时,我有一个意外的输出。

以下是代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/sem.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<sys/wait.h>
#include "display.h"

int main(int argc,char *argv[]){

key_t key1 = 12345;
int semid;
unsigned short semval;
int  i;
int childpid;

struct sembuf wit,signal;

wit.sem_num = 0;
wit.sem_op = -1;
wit.sem_flg = SEM_UNDO;

signal.sem_num = 0;
signal.sem_op = 1;
signal.sem_flg = SEM_UNDO;

semid = semget(key1,1,IPC_CREAT);
//  printf("Allocating the semaphore: %s\n",strerror(errno));

semval = 1;
semctl(semid,0,SETVAL,semval);
//  printf("Setting semaphore value to %d: %s\n",semval,strerror(errno));

semval = semctl(semid,0,GETVAL);
//  printf("Initialized Semaphore value to %d: %s\n",semval,strerror(errno));
sleep(1);
childpid = fork();

if(childpid==0){         /*process 2 */
    for(i=0;i<10;i++){
        semop(semid,&wit,1);
        semctl(semid,0,GETVAL,&semval);
        display("cd\n");
        semop(semid,&signal,1);
    }
    semctl(semid,0,GETVAL,&semval);
    return 0;
}

for(i=0;i<10;i++){
    semop(semid,&wit,1);   /* process 1*/
    semctl(semid,0,GETVAL,&semval);
    display("ab");
    semop(semid,&signal,1);
}
semctl(semid,0,GETVAL,&semval);
sleep(1);
semctl(semid,0,IPC_RMID);
//  printf("\nSemaphore removed from the System = %s\n",strerror(errno));
return 0;
}

所以当我使用“sudo ./mycodehere”命令执行我的代码时,一切顺利,输出正确:

abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd

但是如果我正常执行它,“。/ mycodehere”结果就不一样了:

acbda
bcadb
acbda
bcadb
acbda
bcadb
acbd
cd
cd
cd

有人可以解释一下为什么会发生这种情况,如果可能的话,我应该在哪里修理它?非常感谢! 差点忘了.display.c文件:

#include <stdio.h>
#include <unistd.h>
#include "display.h"

void display(char *str)
{
  char *p;
  for (p=str; *p; p++)
  {
    write(1, p, 1);
    usleep(100);
  }
}

1 个答案:

答案 0 :(得分:1)

这一行

semid = semget(key1,1,IPC_CREAT);

无法正确设置信号量权限。权限都为零。

根据semget specification

  

sem_perm.mode 的低位9位应设置为等于    semflg 的低位9位。

根据Linux man page

  

创建后,参数semflg的最低9位   定义信号量的权限(对于所有者,组和其他人)   组。这些位具有相同的格式,并且具有相同的含义   open参数的模式参数(2)(尽管执行权限不是   对信号量有意义,写权限意味着权限   改变信号量值。)

您的代码必须是这样的:

semid = semget(key1,1,IPC_CREAT | 0660 );

但是现在你的信号量可能已经存在且权限错误。