[Linux管道和IPC]使用信号量和共享内存进行父子进程通信

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define SHM_SIZE 1024    //共享内存的大小
int main(int argc,char *argv[])
{
  int ret,        //临时变量
  pid,        //进程id
  sme_id,        //保存信号量描述符
  shm_id;        //保存共享内存描述符
  key_t     sme_key,    //保存信号量键值
  shm_key;    //保存共享内存键值
  char *shmp;        //指向共享内存的首地址
  struct shmid_ds dsbuf;    //定义共享内存信息结构变量
  struct sembuf lock = {0, -1, SEM_UNDO};        //信号量上锁操作的数组指针
  struct sembuf unlock = {0, 1, SEM_UNDO | IPC_NOWAIT};//信号量解锁操作的数组指针
  shm_key = ftok(*(argv+1), 2);    //获取信号量键值
  if(shm_key < 0)
  {
    perror("ftok");    //调用ftok函数出错
    exit(0);
  }
  sme_id = semget(shm_key, 1, IPC_CREAT | 0666);    //获取信号量ID
  if(sme_id < 0)
  {
    perror("semget");  //调用semget函数出错
    exit(0);
  }
  shm_key = ftok(*(argv+2), 1);    //获取共享内存键值
  if(shm_key < 0)
  {
    perror("ftok");
    exit(0);
  }
  shm_id = shmget(shm_key, SHM_SIZE, IPC_CREAT | 0666);        //获取共享内存ID
  if(shm_id < 0)
  {
    perror("shmget");
    exit(0);
  }
  shmp = shmat(shm_id, NULL, 0);        //映像共享内存
  if((int)shmp == -1)
  {
    perror("shmat");
    exit(0);
  }
  pid = fork();            //创建子进程
  if(pid < 0)
  {
    perror("fork");
    exit(0);
  }
  else if(pid == 0)        //子进程
  {
    ret = semctl(sme_id, 0, SETVAL, 1);        //初始化信号量,初值设为1
    if(ret == -1)
    {
      perror("semctl");
      exit(0);
    }
    ret = semop(sme_id, &lock, 1);        //申请访问共享资源,锁定临界资源
    if(ret == -1)
    {
      perror("semop lock");
      exit(0);
    }
    sleep(4);            //让子进程睡眠4秒
    strcpy(shmp, "hello\n");    //往共享内存写入数据
    if(shmdt((void *)shmp) < 0)    //使共享内存脱离进程地址空间
    {
      perror("shmdt");            
    }
    ret = semop(sme_id, &unlock, 1);        //解锁临界资源
    if(ret == -1)
    {
      perror("semop unlock");
      exit(0);
    }
  }
  else                //父进程
  {
    sleep(1);        //先让子进程运行
    ret = semop(sme_id, &lock, 1);        //申请访问共享资源,锁定临界资源
    if(ret == -1)
    {
      perror("semop lock");
      exit(0);
    }
    if(shmctl(shm_id, IPC_STAT, &dsbuf) < 0)    //获取共享内存信息
    {
      perror("shmctl");
      exit(0);
    }
    else            /* 共享内存的状态信息获取成功 */
    {
      printf("Shared Memory Information:\n");
      printf("\tCreator PID: %d\n", dsbuf.shm_cpid);         /* 输出创建共享内存进程的标识符 */
      printf("\tSize(bytes): %d\n",dsbuf.shm_segsz);         /* 输出共享内存的大小 */
      printf("\tLast Operator PID: %d\n",dsbuf.shm_lpid);     /* 输出上一次操作共享内存进程的标识符 */
      printf("Received message : %s\n", (char *)shmp);        /* 从共享内存中读取数据 */ 
    }
    if(shmdt((void *)shmp) < 0)    //使共享内存脱离进程地址空间
    {
      perror("shmdt");
      exit(0);            
    }        
    ret = semop(sme_id, &unlock, 1);        //解锁临界资源
    if(ret == -1)
    {
      perror("semop unlock");
      exit(0);
    }
    if(shmctl(shm_id, IPC_RMID, NULL) < 0)    /* 删除前面创建的共享内存 */ 
    {
      perror("shmctl");
      exit(0);            
    }
    ret = semctl(sme_id, 0, IPC_RMID, NULL);    //删除信号量
    if(ret == -1)
    {        
      perror("semctl");
      exit(0);        
    }
  }    
  return 0;
}

文章标题:[Linux管道和IPC]使用信号量和共享内存进行父子进程通信
当前链接:http://ybzwz.com/article/pgodoc.html