【问题标题】:POSIX in C semaphore with fork and shared memory,C 信号量中的 POSIX,带有 fork 和共享内存,
【发布时间】:2015-01-03 23:42:38
【问题描述】:

我正在尝试用信号量和分叉和共享内存做一个程序

父假设创建共享内存并将数字插入缓冲区打印完成 然后孩子将从共享内存中读取并打印数字的总和 程序运行,但只有父打印完成,而孩子没有做任何事情,

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

#include <netinet/in.h>
#include <netdb.h> 

#include<netinet/in.h>
#include<netdb.h>
#include<sys/wait.h>
#include<unistd.h>

#include <sys/shm.h>




char buffer[10];
char *data; 
    int commNo =0;
    key_t key;
    int shmid;
    char *shrmem;
    int mode;

void error(char *msg)
{
    perror(msg);
    exit(0);
}
int rem[10];

key_t key; /* key to pass to semget() */ 
key_t key1; /* key to pass to semget() */ 
key_t key2; /* key to pass to semget() */ 
key_t key3; /* key to pass to semget() */ 
int semflg; /* semflg to pass tosemget() */ 
int nsems; /* nsems to pass to semget() */ 
int semid; /* return value from semget() */ 
#define   MAX_COUNT  200
#define  N  100      /* shared buffer of size 100 */

void  ChildProcess(void);                /* child process prototype  */
void  ParentProcess(void);               /* parent process prototype */




//things for ftok 
char *path = "/tmp";
int id = 'S';
//create sembuf

  //struct sembuf{
    //            ushort  sem_num;        /* semaphore index in array */
      //          short   sem_op;         /* semaphore operation */
        //        short   sem_flg;        /* operation flags */
        //};



int locksem = 1;     /* binary semaphore for  locking-unlocking: initiall  unlocked : 1 */
int emptysem = 100;  /* counting semaphore for  empty slots */
int fullsem = 0;      /* counting semaphore for  filled slots*/


 struct sembuf oplock;// = (struct sembuf *) malloc(2*sizeof(struct sembuf));
//static struct sembuf oplock;
//oplock.sem_num = 0;
//oplock.sem_op = -1;
//oplock.sem_flg = SEM_UNDO;

struct sembuf opunlock; // = (struct sembuf *) malloc(2*sizeof(struct sembuf));

//static struct sembuf opunlock;
//opunlock.sem_num = 0;
//opunlock.sem_op = 1;
//opunlock.sem_flg = SEM_UNDO;



void creatmemory(){



      /* make the key: */
    if ((key = ftok("/tmp",1)) == -1) {

        perror("ftok");
        //clientnumber
        exit(1);
    }
      /* connect to (and possibly create) the segment: */
    if ((shmid = shmget(key, 15, 0644| IPC_CREAT)) == -1) {

        perror("shmget");
        exit(1);
    }


     /* attach to the segment to get a pointer to it: */

    data = shmat(shmid, (void *)0, 0);

    if (data == (char *)(-1)) {

        perror("shmat");
        exit(1);
    }


}




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

     nsems = 1;


//static struct sembuf oplock;
oplock.sem_num = 0;
oplock.sem_op = -1;
oplock.sem_flg = SEM_UNDO;


//static struct sembuf opunlock;
opunlock.sem_num = 0;
opunlock.sem_op = 1;
opunlock.sem_flg = SEM_UNDO;


//to create new one
semflg = IPC_CREAT;


         /* Get unique key for semaphore. */
if ((key1 =  ftok(path,1)) == (key_t) -1) {
    perror("IPC error: ftok"); exit(1);
}
/* Get unique key for semaphore. */
if ((key2 =  ftok(path,2)) == (key_t) -1) {
    perror("IPC error: ftok"); exit(1);
}
/* Get unique key for semaphore. */
if ((key3 =  ftok(path,3)) == (key_t) -1) {
    perror("IPC error: ftok"); exit(1);
}


     pid = fork();
     if (pid == 0) {

     //***************************************************************************************************************



//
int n =0;
while(n < 3){

locksem = semget(key1, nsems, semflg);   /* open-create locksem*/
emptysem = semget(key2, nsems, semflg);
fullsem = semget(key3, nsems, semflg);
    semop(fullsem,&oplock,1);  /* check filled slots */
    semop(locksem,&oplock,1);      /* lock shared buffer*/
   // itx= remove_item(); 
   /* remove an item from buffer */
   int i;
   for (i =0; i<10; i++){
   rem[i] = data[i];}
   bzero(buffer,10);
   bzero(data,strlen(data));
    /* detach from the segment: */
    if (shmdt(data) == -1) {
        perror("shmdt");
        exit(1);
    }
    semop(locksem,&opunlock,1);  /* unlock the buffer */
    semop(emptysem,&opunlock,1);  /* increment emptysem*/
    //consume_item(itx);
    int sum = 0;
for(i =0; i<10; i++){
sum += rem[i];}
printf("the sum is:%d \n", sum);
    n++;} 
    }

         //consumer();
     else 
     {

      creatmemory();
     int n =0;
while( n < 3) {  

locksem = semget(key1, nsems, semflg);   /* open-create locksem*/
emptysem = semget(key2, nsems, semflg);
fullsem = semget(key3, nsems, semflg);

bzero(buffer,10);
int i;
for(i =0; i<10; i++)
buffer[i] = i;

    semop(emptysem,&oplock,1);  /* check empty slots */
    semop(locksem,&oplock,1);      /* lock shared buffer*/
/* insert item into the buffer */

strncpy(data, buffer, strlen(buffer));  
printf("done \n");
    semop(locksem,&opunlock,1);  /* unlock the buffer */
    semop(fullsem,&opunlock,1);  /* increment fullsem*/

    sleep(10);      

     n++;}  
     }
         // producer();


}

【问题讨论】:

  • 建议重新发布代码,不带制表符,在单独的行上加上右括号'}',每行只有一个语句,等等此外,此代码甚至没有接近干净编译,有大约 20 多个错误和警告。例如,调用了函数“exit”但没有“#include ”建议编译时启用所有警告,然后修复这些警告
  • 此代码无法协调共享内存部分的创建/设置/读取/销毁。如果出现问题,'error()' 函数将无法清除信号量、释放共享内存等。

标签: c posix


【解决方案1】:

这是一个实际编译和链接干净的代码版本:

#define  _XOPEN_SOURCE (1) // needed by sys/ipc.h
#include <sys/types.h>

#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

#include <stdlib.h> // exit()
#include <string.h>
#include <strings.h> // bzero())

#include <netinet/in.h>
#include <netdb.h>

#include <netinet/in.h>
#include <netdb.h>
#include <sys/wait.h>
#include <unistd.h>

#include <sys/shm.h>




char buffer[10];
char *data;
int commNo =0;
key_t key;
int shmid;
char *shrmem;
int mode;

void error(char *);


int rem[10];

key_t key; /* key to pass to semget() */
key_t key1; /* key to pass to semget() */
key_t key2; /* key to pass to semget() */
key_t key3; /* key to pass to semget() */
int semflg; /* semflg to pass tosemget() */
int nsems; /* nsems to pass to semget() */
int semid; /* return value from semget() */
#define   MAX_COUNT  200
#define  N  100      /* shared buffer of size 100 */

void creatmemory( void );




//things for ftok
char *path = "/tmp";
int id = 'S';
//create sembuf

  //struct sembuf{
    //            ushort  sem_num;        /* semaphore index in array */
      //          short   sem_op;         /* semaphore operation */
        //        short   sem_flg;        /* operation flags */
        //};



int locksem = 1;     /* binary semaphore for  locking-unlocking: initiall  unlocked : 1 */
int emptysem = 100;  /* counting semaphore for  empty slots */
int fullsem = 0;      /* counting semaphore for  filled slots*/


 struct sembuf oplock;// = (struct sembuf *) malloc(2*sizeof(struct sembuf));
//static struct sembuf oplock;
//oplock.sem_num = 0;
//oplock.sem_op = -1;
//oplock.sem_flg = SEM_UNDO;

struct sembuf opunlock; // = (struct sembuf *) malloc(2*sizeof(struct sembuf));

//static struct sembuf opunlock;
//opunlock.sem_num = 0;
//opunlock.sem_op = 1;
//opunlock.sem_flg = SEM_UNDO;








int main()
{
     pid_t pid;

     nsems = 1;


    //static struct sembuf oplock;
    oplock.sem_num = 0;
    oplock.sem_op = -1;
    oplock.sem_flg = SEM_UNDO;


    //static struct sembuf opunlock;
    opunlock.sem_num = 0;
    opunlock.sem_op = 1;
    opunlock.sem_flg = SEM_UNDO;


    //to create new one
    semflg = IPC_CREAT;


    /* Get unique key for semaphore. */
    if ((key1 =  ftok(path,1)) == (key_t) -1) {
        perror("IPC error: ftok"); exit(1);
    }

    /* Get unique key for semaphore. */
    if ((key2 =  ftok(path,2)) == (key_t) -1) {
        perror("IPC error: ftok"); exit(1);
    }

    /* Get unique key for semaphore. */
    if ((key3 =  ftok(path,3)) == (key_t) -1) {
        perror("IPC error: ftok"); exit(1);
    }


    if( 0 == (pid = fork() ) )
    { // then, child process

        int n =0;
        for(;n<3;n++)
        {

            locksem = semget(key1, nsems, semflg);   /* open-create locksem*/
            emptysem = semget(key2, nsems, semflg);
            fullsem = semget(key3, nsems, semflg);

            semop(fullsem,&oplock,1);  /* check filled slots */
            semop(locksem,&oplock,1);      /* lock shared buffer*/

            // itx= remove_item();
            /* remove an item from buffer */
            int i = 0;
            for (;i<10; i++)
            {
                rem[i] = data[i];
            } // end for

            bzero(buffer,10);
            bzero(data,strlen(data));

            /* detach from the segment: */
            if (shmdt(data) == -1)
            {
                error( "shmdt" );
            } // error() does not return

            // implied else, shmdt successful

            semop(locksem,&opunlock,1);  /* unlock the buffer */
            semop(emptysem,&opunlock,1);  /* increment emptysem*/
            //consume_item(itx);

            int sum = 0;
            for(i =0; i<10; i++)
            {
                sum += rem[i];
            } // end for

            printf("the sum is:%d \n", sum);
        } // end while
    }

    else
    { // else parent process
        creatmemory();

        int n =0;
        for(;n<3;n++)
        {
            locksem = semget(key1, nsems, semflg);   /* open-create locksem*/
            emptysem = semget(key2, nsems, semflg);
            fullsem = semget(key3, nsems, semflg);

            bzero(buffer,10);
            int i;
            for(i =0; i<10; i++)
            {
                buffer[i] = i;
            } // end for

            semop(emptysem,&oplock,1);  /* check empty slots */
            semop(locksem,&oplock,1);      /* lock shared buffer*/

            /* insert item into the buffer */
            strncpy(data, buffer, strlen(buffer));
            printf("done \n");

            semop(locksem,&opunlock,1);  /* unlock the buffer */
            semop(fullsem,&opunlock,1);  /* increment fullsem*/

            sleep(10);
        } // end for
    } // end if

    return(0);
} // end function: main


void creatmemory()
{
    /* make the key: */
    if ((key = ftok("/tmp",1)) == -1)
    {
        error( "ftok" ); // error does not return
    }

    // implied else, ftok successful

    /* connect to (and possibly create) the segment: */
    if ((shmid = shmget(key, 15, 0644| IPC_CREAT)) == -1)
    {
        error( "shmget" ); // error does not return
    }

    // implied else, shmget successful

    /* attach to the segment to get a pointer to it: */
    data = shmat(shmid, (void *)0, 0);

    if (data == (char *)(-1))
    {
        error( "shmat" ); // error does not return
    }

    // implied else, shmat successful
} // end function: creatmemory


void error(char *msg)
{
    perror(msg);
    exit(0);
} // end function: error

我建议使用互斥体而不是信号量来保护关键代码/数据。

顺便说一句:除非被销毁,否则信号量将永远存在。

在 Linux 中,它们成为 /proc 目录树的一部分。

【讨论】:

  • 进程共享的信号量和互斥量可以永远存在。线程共享的信号量和互斥量不会。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2023-03-19
  • 2021-01-19
相关资源
最近更新 更多