我正在尝试用C++解决我的学校项目。我必须创建15个进程,并且它们必须按顺序运行,这意味着这些进程按此顺序运行0 1 2 3 4 5 6 7 8 9 10 11 12 13 140。它可以工作,但是当我尝试从内存中删除信号量时我从semctl得到错误。最后,我使用“semctl(semid,0,IPC_RMID,0”),但出现错误22,这意味着EINVAL,但没有意义,因此我尝试从父进程中删除信号量,因此我应该有权限这样做。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/wait.h>

union semun {
            int val;
            struct semid_ds *buf;
            ushort *array;
                 };
struct sembuf sops[1];
int semid;

 int wait_sem(int index, int pid){
       fprintf(stderr, "\n------- Proces %d do operation wait (-1) on semaphore %d\n",pid, index);
                  sops[0].sem_num = index;
                  sops[0].sem_op = -1;
                  sops[0].sem_flg = 0 ;
     if  (semop(semid, sops, 1)<0){
             perror("semop fail wait");
             return 1;
         }
         else
             return 0;
  }

 int signal_sem(int index, int pid){
      fprintf(stderr, "\n++++++ Proces %d vykonava operaciu signal (1) na semafore %d\n",pid,index);
            sops[0].sem_num = index;
            sops[0].sem_op = 1;
            sops[0].sem_flg = 0;
     if  (semop(semid, sops, 1)<0){
            perror("semop fail signal");
            return 1;
         }
         else
            return 0;
  }

 void createSem(key_t paKey, int paSemFlg, int paNsems)
 {
     printf ("uid=%d euid=%d\n", (int) getuid (), (int) geteuid ());
     (semid = semget(paKey, paNsems, paSemFlg));


     for (int i = 0; i < paNsems; ++i) {
         semctl(semid, i, SETVAL, 0);
     }
 }

 void kic()
 {
     printf("\naaaaaaaaaaaaaa\n");
 }

 int  main() {

          key_t key = 1234;
          int semflg = IPC_CREAT | 0666;
          int nsems = 15;
          int semid;
          fprintf(stderr, "%d=", sops);
          createSem(IPC_PRIVATE, semflg, nsems);
        if (semid == -1) {
            perror("semget: semget failed");
        return 1;
        }
        else
            fprintf(stderr, "semget: semget sucess: semid = %d, parrent pid %d\n", semid, getpid());


   int PROCESS_ID = 0;
   pid_t PID;

   for (int i = 1; i < nsems; i++) {
       PID = fork();
       if(PID == 0)
       {
           PROCESS_ID = i;
           break;
       }
   }

   if(PID == -1)
   {
       printf("\nPID ERROR");
   }

   if(PID != 0) //parrent
   {
       printf("\n\nparrent with ID %d", PROCESS_ID);
       signal_sem(PROCESS_ID+1, PROCESS_ID);
       wait_sem(PROCESS_ID, PROCESS_ID);
       printf ("uid=%d euid=%d\n", (int) getuid (), (int) geteuid ());
       printf("\nEND %d\n", getpid());
       int s;
       wait(&s);

       if((semctl(semid, 0, IPC_RMID, 0))==-1)
       {
           int a = errno;
           printf("\nERROR IPC_RMID %d\n", a);
       }
   }

   if(PID == 0)//child
   {
       if(wait_sem(PROCESS_ID, PROCESS_ID) == 0){
           printf("\nI am child with ID %d", PROCESS_ID);
           int ID_NEXT_PROCESS = 1+PROCESS_ID;
           if(ID_NEXT_PROCESS == nsems)
               ID_NEXT_PROCESS = 0;
           signal_sem(ID_NEXT_PROCESS, PROCESS_ID);
           return 0;
       }

   }
    return 0;
  }

最佳答案

您有两个semid。一个在全局范围内,另一个在main本地(它在全局范围内阴影,您应该看到警告)。 createSem仅知道全局一个,并对其进行初始化。 semctl直接由main调用,并传递给本地垃圾,这是垃圾。

关于c++ - IPC_RMID在使用C++的Linux上不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33925670/

10-09 05:22