System V 信号量操作,进程间通信(…

来源:互联网 发布:男士服装搭配软件 编辑:程序博客网 时间:2024/06/12 01:18
   首先说明下System Vsemaphore和Posix semaphore的区别
   二者是信号量的两组程序设计接口函数。POSIX semaphore来源于POSIX技术规范的实时扩展方案(POSIX Realtime Extension),常用于线程;System V semaphore,常用于进程的同步。这两者非常相近,但它们使用的函数调用各不相同。前一种的头文件为semaphore.h,函数调用为sem_open()(Open Named Semaphore), sem_init() (Initialize Unnamed Semaphore),sem_wait(),sem_post(),sem_destory()等等。后一种头文件为<sys/sem.h>,函数调用为semctl(),semget(),semop()等函数。
  本例中的信号量使用机制来源于mm共享库,一旦锁住便不可再进入,这里使用了structsembuf结构的二维数组,是为了同时操作信号集,如dolock()后再dolock()就会被阻塞(只能等待dounlock()解救),因为my_dolock[1].sem_op= 1使信号值为1,而在my_dolock[0].sem_op = 0中,只要当sem_op不为0就阻塞
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h>

union semun {
    int val;                // used for SETVAL only 
    struct semid_ds *buf;      // usedfor IPC_STAT and IPC_SET 
    ushort *array;           // used for GETALL andSETALL 
};

#if 01
int semid;
static union  semun my_semctlarg;
static struct sembuf my_dolock[2];
static struct sembuf my_dounlock[1];

int newSem();

void initSemBuf()
{
       my_dolock[0].sem_num = 0;
       my_dolock[0].sem_op = 0;
       my_dolock[0].sem_flg = 0;

       my_dolock[1].sem_num = 0;
       my_dolock[1].sem_op = 1;
       my_dolock[1].sem_flg = SEM_UNDO;

       my_dounlock[0].sem_num = 0;
       my_dounlock[0].sem_op = -1;
       my_dounlock[0].sem_flg = SEM_UNDO;

       semid = newSem();
}

int dolock()
{
       int ret = -1;
* __sops, which is a pointer to the struct sembuf that youfilled with your semaphore commands. If you want, though, you canmake an array of struct sembufs in order to do a whole bunch ofsemaphore operations at the same time. The way semop() knows thatyou're doing this is the nsop argument, which tells how many structsembufs you're sending it. If you only have one, well, put 1 asthis argument.
       while (((ret = semop(semid, my_dolock, 2))< 0) && (errno ==EINTR))
              ;

       if (ret < 0)
       {
              perror("do lock semop :");
              abort();
       }

       return 0;
}

int dounlock()
{
       int ret = -1;

       while (((ret = semop(semid, my_dounlock, 1))< 0) && (errno ==EINTR))
              ;

       if (ret < 0)
       {
              perror("do unlock semop :");
              abort();
       }

       return 0;
}

void showSem()
{
       fprintf(stdout, "sem val: %d\n", semctl(semid,0, GETVAL));
}

int newSem()
{
       int semid = semget(321034, 10, IPC_CREAT |IPC_EXCL | 0666);
       if (semid < 0)
       {
              perror("semget : ");
              abort();
       }

       my_semctlarg.val = 0;
       semctl(semid, 0, SETVAL, my_semctlarg);

       return semid;
}

void freeSem()
{
       semctl(semid, 0, IPC_RMID);
}

int main()
{
       initSemBuf();

       int limit = 5;
       pid_t pid;

       if((pid = fork()) < 0){
              freeSem();
              return -1;
       }

       if(0 == pid){
             srand(time(NULL)^getpid());
              int i = 0;

              while(i++ <limit){
                    dolock();
                     int sec =rand() & 255;

                    fprintf(stdout, "child doing work...\nafter %dms finish...\n\n",sec);
                    usleep(sec);

                    dounlock();
              }

       }else{
             srand(time(NULL)^getpid());
              int i = 0;

              while(i++ <limit){
                    dolock();
                     int sec =rand() & 255;

                    fprintf(stdout, "parent doing work...\nafter %dms finish...\n\n",sec);
                    usleep(sec);

                    dounlock();
              }

       }

       usleep(1000);
       freeSem();
       return 0;
}

#endif
原创粉丝点击