Linux进程间通信——信号量

来源:互联网 发布:电魂网络新游戏 编辑:程序博客网 时间:2024/05/24 01:15

什么是信号量

      为了防止出现多个程序同时访问一个共享数据资源而引发的问题,需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区。信号量就可以提供这样一种访问机制。 信号量的本质是一种数据操作锁,是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步功能。

信号量的工作原理

   信号量能够进行的两种操作分别是:等待信号P(sv)和发送信号V(sv)
   ☆P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就将该进程挂起;
   ☆V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1。

Linux的信号量机制

   Linux提供的信号量接口有:

   semget函数

int semget(key_t key, int num_sems, int sem_flags);

      作   用:创建一个新信号量或取得一个已有信号量;

         参   数:key是键值,它要与已有的键值进行比较,已有的键值指在内核中已存在的其它信号量集合的键值;

                   num_sems指定需要的信号量数目,它的值几乎总是1;

                   sem_flags是一组标志,当想要当信号量不存在时创建一个新的信号量。IPC_CREAT | IPC_EXCL可以                          创建一个新的、唯一的信号量,如果信号量已存在,返回一个错误。

      返回值:如果成功,则返回信号量集合的IPC识别号如果为-1,则出现错误;

    semop函数

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

       作   用:改变信号量的值;

       参   数:sem_id是由semget返回的信号量标识符;

                    num_sem_ops是说我们仅仅执行了一个操作;

                    sem_opa参数指向类型为sembuf的一个数组,这个结构在/inclide/linux/sem.h 中声明:

struct sembuf{  

    short sem_num; /* 在数组中信号量的索引值 */ 

    short sem_op;  /* 信号量操作值(正数、负数或0) */。  

    short sem_flg; /* 操作标志,通常为SEM_UNDO*/ 

}; 

   「SEM_UNDO当操作信号量(semop)时,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号           量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时              归还给信号量,从而使另外一个进程可以继续工作,防止其他进程因为得不到信号量而发生“死锁现象”。                  为此一 般建议使用SEM_UNDO。

    若通过kill命令把其中一个进程杀死,且该进程还没有执行V操作释放资源。若使用SEM_UNDO标志,则操作系           统将自动释放该进程持有的信号量,从而使得另外一个进程可以继续工作。若没有这个标志,另外进程将P操               作永远阻塞。

      返回值:如果所有的操作都执行,则成功返回0;如果为-1,则出错。

    semctl函数

int semctl(int semid,int semnum, int cmd, union semun arg);
     作   用:控制信号量信息;

       参   数:cmd参数表示在集合上执行的命令(通常为SETVAL(用联合体中val成员的值设置信号量集合中单个信                      号量的值)或者IPC_RMID(从内核中删除信号量集合

                  arg参数的类型为semun,这个特殊的联合体在 include/linux/sem.h中声明:

union semun{

int val;                /* value for SETVAL */

struct semid_ds *buf;   /* buffer for IPC_STAT & IPC_SET */

ushort *array;          /* array for GETALL & SETALL */

struct seminfo *__buf;  /* buffer for IPC_INFO */

void *__pad;

};



使用信号量进行通信

   comm.h

    

   comm.c

     

     

     

     

   test_sem.c

     

     

   运行结果:

     

   分析:

     因为每个程序都在其进入临界区后和离开临界区前打印一个字符,所以每个字符是成对出现的。

    


0 0