简体   繁体   English

在C中使用信号量和共享内存

[英]Working with semaphores and shared memory in C

The program should create 200000 integers and write 2000 to a shared memory. 该程序应创建200000整数并将2000写到共享内存中。 A forked process should read 2000 from shared memory and the parent should write the next 2000 to shared memory. 分叉的进程应从共享内存中读取2000,而父进程应将下一个2000写入共享内存。

if i use the code below without sleep, the parent first creates all 200000 integers and then the child reads the same integers from shared memory. 如果我使用下面的代码不睡觉,则父级首先创建所有200000整数,然后子级从共享内存中读取相同的整数。

With sleep everything looks good, but we have to use semaphore. 有了睡眠,一切看起来都不错,但是我们必须使用信号量。

shm.c (parent): shm.c(父级):

    #include <stdio.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/sem.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/resource.h>
    #include <sys/wait.h>

    #define N_DATA 200000
    #define N_SHARED 2000
    #define LOCK       -1
    #define UNLOCK      1

    static struct sembuf semaphore;

    char shmidArg[32];
    char semidArg[32];
    int *shmData;
    int i, j;
    int status;
    char *strsignal(int sig);
    pid_t pid;

    static int shmid;
    static int semid;

    char *strsignal(int sig);

    /** Semaphore Operation */
    static int semaphore_operation (int op) {
       semaphore.sem_num = 1;
       semaphore.sem_op = op;
       semaphore.sem_flg = IPC_NOWAIT;
       if( semop (semid, &semaphore, 1) == -1) {
          perror(" semop ");
          exit (EXIT_FAILURE);
       }
       return 1;
    }

    int main(int argc, char **argv) {
      /* Ein Shared-Memory-Segment einrichten */
      shmid = shmget(IPC_PRIVATE, N_SHARED*sizeof(int), IPC_CREAT | SHM_R | SHM_W);
      if (shmid == -1) {
       perror("shmid");
       exit(1);
      }

      printf("Shared-Memory-ID: %d\n",shmid);

      /* Pointer zu Shared-Memory-Segment erhalten */
      shmData = (int *)shmat(shmid,0, 0);
      if (shmData == (int *)(-1)) {
          perror("shmat");
          exit(1);
      }

      /* Semaphore anlegen */
      semid = semget(IPC_PRIVATE, 1, IPC_CREAT | SHM_R | SHM_W);
      if (semid < 0) {
       perror("semid");
       exit(1);
      }

      printf ("Semaphor-ID : %d\n", semid);

      /* Semaphor mit 1 initialisieren */
    if (semctl (semid, 0, SETVAL, (int) 1) == -1) {
       perror("semctl");
    }

    snprintf(shmidArg,32, "%d", shmid);
    snprintf(semidArg,32, "%d", semid);

      /** erstellen des Kindprozesses */
      pid = fork();

      // Kindprozess
      if (pid == 0) {
        execlp("./shm_child",shmidArg,semidArg,NULL);
      } else if (pid < 0) {
            perror("Kindprozess konnte nicht erzeugt werden!");
            return 1;
        }
      // Elternprozess
      else {
        /** ininitalisieren des Zufallsgenerator durch aktuellen Zeitstempel */
        srand48(time(NULL));
        for(i=0;i<N_DATA;i=i+N_SHARED) {
          semaphore_operation(LOCK);
          for (j=0; j<N_SHARED; j++) {
            shmData[j] = lrand48();
            //MSZ
            //printf("SHM-->%d-->%d\n",i+1,shmData[i]);
          }
    //      if(i == 0 || i == 2000) {
            printf("Parent-->%d-->0-->%d\n",i,shmData[0]);
            printf("Parent-->%d-->1999->%d\n",i,shmData[1999]);
    //      }
          semaphore_operation(UNLOCK);
          //sleep(1);
        }
      }

      //MSZ
      //sleep(2);
      printf("PID: %d\n", pid);

      if (waitpid(pid, &status, 0) == -1) {
            perror("wait konnte nicht erzeugt werden!");
            return 1;
        }

        if (WIFEXITED(status)) {
            printf("Exitcode: %d\n", WEXITSTATUS(status));
        semctl (semid, 0, IPC_RMID, 0);
        shmctl (shmid, IPC_RMID, NULL);
        //If process terminaded by a signal
        } else if (WIFSIGNALED(status)) {
            printf("Signal: %d %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
        semctl (semid, 0, IPC_RMID, 0);
        shmctl (shmid, IPC_RMID, NULL);
        }

    }

shm_child.c (Child): shm_child.c(儿童):

        #include <stdio.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/sem.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    #define N_DATA 6000
    #define N_SHARED 2000
    #define LOCK       -1
    #define UNLOCK      1

    int i,j;
    int *shmData;
    static int shmid;
    static int semid;
    static struct sembuf semaphore;


    /** Semaphore Operation */
    static int semaphore_operation (int op) {
       semaphore.sem_num = 0;
       semaphore.sem_op = op;
       semaphore.sem_flg = SEM_UNDO;
       if( semop (semid, &semaphore, 1) == -1) {
          perror(" semop ");
          exit (EXIT_FAILURE);
       }
       return 1;
    }

    int main(int argc, char **argv) {
      shmid = atoi(argv[0]);
      semid = atoi(argv[1]);

      printf("\nshm_child shared memoryid:%d\n",shmid);
      printf("shm_child Semaphoren-ID:%d\n",semid);

      /* Pointer auf Shared-Memory erstellen */
      shmData = (int *)shmat(shmid,0,0);
      if (shmData == (int *)(-1)) {
          perror("shmat");
          exit(1);
      }


    for(i=0;i<N_DATA;i=i+N_SHARED) {
      semaphore_operation(LOCK);
      for(j=0;j<N_SHARED;j++) {
        //printf("%d-->%d --> %d\n",i,j+1,shmData[j]);
      }
    //  if(i == 0 || i == 2000) {
        printf("child-->%d-->0-->%d\n",i,shmData[0]);
        printf("child-->%d-->1999->%d\n",i,shmData[1999]);
    //  }
      semaphore_operation(UNLOCK);
      sleep(1);
    }

      return 0;
    }

Please help us Thank you guys 请帮助我们,谢谢大家

Edit: Thank you very much for your answers. 编辑:非常感谢您的回答。 I can't mark the right answer because i dont know what its right. 我无法标记正确的答案,因为我不知道它的正确性。 But i dont want try anything more. 但是我不想再尝试了。 15 hours are enough 15小时就够了

The writer process shall give reader a permission to read, and wait for the reading completion. 作者过程应授予读者阅读权限,并等待阅读完成。 After that the reader shall give writer a permission to proceed, and wait for writing completion. 之后,读者应授予作者继续进行的权限,并等待写作完成。

This goal cannot be achieved with a single semaphore. 单个信号量无法实现此目标。 You need two, along the lines of: 您需要遵循以下两个原则:

    // parent aka writer
    writer_barrier = semaphore(UNLOCKED);
    reader_barrier = semaphore(LOCKED);
    start_reader();
    while(...) {
        lock(writer_barrier);
        write_data();
        unlock(reader_barrier);
    }

    // child aka reader
    while(....)
        lock(reader_barrier);
        read_data();
        unlock(writer_barrier);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM