发信人: tcpip (俺的昵称改了), 信区: cnunix
标  题: 本地进程间通信第五讲:信号灯(一)
发信站: 哈工大紫丁香 (Sun Sep 26 17:10:15 1999), 转信

发信人: cpu (奔腾的心), 信区: Solaris
发信站: 华南网木棉站 (Thu Apr 15 13:06:05 1999), 转信

学过操作系统的虫子应该都对信号灯有印象,主要是为进程取得资源提供了
一种互斥机制。互斥资源的初值一般大于0,比如某系统只有一台打印机,那
么可以用一个信号灯来标识这台打印机,初值为1。当有进程要占用这台打印
机的时候,则对信号灯-1(P操作),用完后,对信号灯+1(V操作),所有需
要这台打印机的进程都要遵循这个游戏规则。当打印机被某一进程占用的时候,
其它进程只能阻塞在P操作上,一直到信号灯再次为1。

(1) 函数semget: 取得一组信号灯(注意,是一组,不是一个,各个组员可以
    标识各种不同类别的资源)

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/sem.h>
     int semget(key_t key, int nsems, int semflg);

成功则返回信号灯组的整形标识号,否则返回-1,errno指出错误类型。每个
信号灯数据结构都包含一个分量semval,表示该信号灯的当前值,初始值为0。

key:   是IPC_PRIVATE或者你自己指定一个长整形值,用来唯一地标识将要
        创建的信号灯;
nsems: 要创建的一组信号灯当中的信号灯数;
semflg: 存取权限和创建标志的或。比如 0600 | IPC_CREAT | IPC_EXCL
        存取权限--无须多解释,比如0600,0660 ...
        创建标志
        IPC_CREAT-- 给出key对应的信号灯组不存在则创建之
        IPC_EXCL--  同时指定IPC_CREAT时,若key对应的信号灯
                    组已经存在,则出错返回,errno为EEXIST

(2) 函数semop:信号灯组的操作,这个调用可以派生出所谓的P操作和V操作来。
    注意semop可以对信号灯组中的多个成员同时操作,这体现在该调用的后两
    个参数上。一般一个信号灯标识一个资源,对多个信号灯的同时操作可以在
    现实中体现为一个操作要占用几个资源。
               

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/sem.h>
     int semop(int semid, struct sembuf *sops, size_t nsops);

semid:  就是semget调用返回的信号灯组的标识。
sops:   操作集指针,操作集的每个成员对应信号灯组中某个组员的操作。
        
        sembuf结构的定义:
        sturct sembuf {
            short   sem_num;    /* 信号灯组员的索引,0为第一个信号灯 */
            short   sem_op;     /* 对指定信号灯组员的操作 */
            short   sem_flg;    /* 操作标志的或,包括非阻塞标志IPC_NOWAIT
                                 * 和进程退出取消操作标志SEM_UNDO */
        };

nsops:  操作集的长度,即sops的成员数。

sembuf的sem_op成员是个关键,它规定了对sem_num指定的信号灯进行什么样
的操作:

1.如果sem_op < 0,则对应P操作,当sem_op的绝对值大于该信号灯的semval时,
semop将阻塞或者出错返回(若sem_flg&IPC_NOWAIT为真,则操作不阻塞,errno
为EAGAIN);否则,semval = semval - |sem_op|,操作返回。

2.如果sem_op > 0,则对应V操作,semval = semval + sem_op,操作返回。

3.如果sem_op == 0,则当semval == 0的时候,操作成功返回,否则将阻塞或者
出错返回(同样非阻塞操作由sem_flag指定)。该操作实际上查看某项资源是否
耗尽。

sem_flg一般为0,若sem_flg包含IPC_NOWAIT,则该操作为非阻塞操作,若sem_flg
包含SEM_UNDO,则当进程退出的时候会取消该操作,这个标志在某些情况下是很
有用的,比如某进程做了P操作得到资源,但还没来得及做V操作时就异常退出了,
这样其它进程就只能都阻塞在P操作上了,造成死锁。若采取了SEM_UNDO标志就可
以避免因为进程异常退出而造成死锁。

关于semaphore的进一步操作,请详细看有关信号灯的数据结构struct semid_ds和
struct sem,在/usr/include/sys/sem.h中,另外对semaphore的详细控制请详细
查看函数semctl的manul,比如删除信号灯,置信号灯semval的初值等操作都由该
函数提供。
--

        ******************************************************

               青岛啤酒,可能是世界上最好的啤酒 。。。 。。。

        ******************************************************
※ 修改:.trueip 于 Sep 26 17:14:02 修改本文.[FROM: dns.mtlab.hit.ed]
--
※ 转寄:.华南网木棉站 bbs.gznet.edu.cn.[FROM: dns.mtlab.hit.ed]

--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: trueip.bbs@melon.gzn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:8.294毫秒