通过信号量达到进程对资源占用的互…

来源:互联网 发布:淘宝运营每天做什么 编辑:程序博客网 时间:2024/06/18 07:07
信号量与IPC(管道,FIFO,消息队列)不同,它是一个计数器,用于多进程对共享数据对象的访问。不过信号量到底是一个什么东西呢?简单来说它就是一个标志,实质是一个数字,用来标记占用资源的进程个数。
对于一些特殊的资源,我们可以利用信号量来限制进程对文件资源的访问,举个例子

进程A要对文件F进行操作,但是进程A的动作很慢,在A还没做完时B进程来了,它也要对F操作,这时文件F就会因为AB两个进程同时操作而出现混乱,所以我们要限制进程对文件的操作权限,一般我们都遵循先来后到,所以当A进程对F进行操作的时候,我们不能让其他进程对F进行操作

这里就可以用到信号量。首先,内核中的每一个IPC结构(消息队列,信号量,共享存储段)都有一个非负正数的标识符,这里我们就有一个标识符与信号量对应。文件就比作是信号量,文件名就比作一个叫键值的东西,文件描述符则是信号量的标识符。我们打开一个文件用open函数,用到文件名,而打开一个信号量则用键值(与之对应);打开文件返回文件描述符,打开信号量返回信号量标识符(以后操作该信号量就可以用这个描述符)

就比方我们现在要打开一个信号量集合,我们可以这样操作
semid = semget(key, 1, IPC_CREAT);
semget函数有三个参数,第一个是信号量的键值,第二个是打开/创建信号量集合里面信号量的数目,第三个是一个条件参数,如果对应该键值没有这个信号量则创建这个信号量,返回值是这个信号量集合的标识符
这里这个键值我们怎么知道?所以我们还要来确定这个键值,理论上键值可以是任意正数,但是为了不会重复定义键值,我们用ftok函数
key = ftok("/home", 1);
第一个参数是路径,第二个参数是项目ID(也可以任意),返回的值就是一个键值,于是用这个键值就可以利用semget函数打开/创建一个信号量集合了。

我们还可以用semctl函数对这个信号量集合的数值进行操作
semctl(int semid, int semnum, int cmd, ...);
第一个参数是信号量集合的标识符,第二个参数表示要对这个信号量集合里面的第几个信号进行操作,第三个是进行什么操作
cmd可取(常用)
GETVAL       得到信号量的值
SETVAL       设置信号量的值
值为1,则表示还允许一个进程来操作
值为2,则表示还允许二个进程来操作
。。。

当用信号量对文件进行保护的时候,在操作之前要对该信号量进行-1的操作,具体如下
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = -1;
semop(semid, &sops, 1); 若这个时候信号量的值已经为0,则该进程进入等待,直到可以用这个文件资源为止(即信号量的值大于0)

当对一个文件操作结束后,需要释放信号量,即对信号量进行+1的操作,同-1的操作
sops.sem_num = 0;
sops.sem_op = 1;
semop(semid, &sops, 1);

这样就可以对文件的操作进行保护

原创粉丝点击