加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

System V IPC 之信号量

发布时间:2020-12-13 14:11:49 所属栏目:Linux 来源:网络整理
导读:",而 System V 信号量的引用头文件是 " "。 解决互斥共享资源的同步问题 而引入的机制。信号量的实质是整数计数器,其中 记录了可供访问的共享资源的单元个数 。本文接下来提到的信号量都特指 System V IPC 信号量。 sem * sem_perm :对应于该信号量集的 i

  • ",而 System V 信号量的引用头文件是 ""。

解决互斥共享资源的同步问题而引入的机制。信号量的实质是整数计数器,其中记录了可供访问的共享资源的单元个数。本文接下来提到的信号量都特指 System V IPC 信号量。

sem *

sem_perm:对应于该信号量集的 ipc_perm 结构(该结构的详情请参考《System V IPC 之内存共享》)指针。sem_base:sem 结构指针,指向信号量集中第一个信号量的 sem 结构。sem_nsems:信号量集中信号量的个数。sem_otime:最近一次调用 semop 函数的时间。sem_ctime:最近一次改变该信号量集的时间。

semval; semncnt; semzcnt;

#include

<span style="color: #0000ff">int semget(key_t key,<span style="color: #0000ff">int nsems,<span style="color: #0000ff">int semflg);

#include

<span style="color: #0000ff">int semop(<span style="color: #0000ff">int semid,<span style="color: #0000ff">struct sembuf *sops,size_t nsops);

sem_num;

sem_op > 0:表示进程对资源使用完毕,交回该资源。此时信号量集的 semid_ds 结构的 sem_base.semval 将加上 sem_op 的值。若此时设置了 SEM_UNDO 位,则信号量的调整值将减去 sem_op 的绝对值。sem_op = 0:表示进程要等待,直至 sem_base.semval 变为 0。sem_op < 0:表示进程希望使用资源。此时将比较 sem_base.semval 和 sem_op 的绝对值大小。如果 sem_base.semval 大于等于 sem_op 的绝对值,说明资源足够分配给此进程,则 sem_base.semval 将减去 sem_op 的绝对值。若此时设置了 SEM_UNDO 位,则信号量的调整值将加上 sem_op 的绝对值。如果 sem_base.semval 小于 sem_op 的绝对值,表示资源不足。若设置了 IPC_NOWAIT 位,则函数出错返回,否则 semid_ds 结构中的 sem_base.semncnt 加 1,进程等待直至 sem_base.semval 大于等于 sem_op 的绝对值或该信号量被删除。

#include

<span style="color: #0000ff">int semctl(<span style="color: #0000ff">int semid,<span style="color: #0000ff">int semnum,<span style="color: #0000ff">int cmd,union semun arg);

semid_ds * *array; };

GETALL:获得 semid 所表示的信号量集中信号量的个数,并将该值存放在无符号短整型数组 array 中。GETNCNT:获得 semid 所表示的信号量集中的等待给定信号量锁的进程数目,即 semid_ds 结构中 sem.semncnt 的值。GETPID:获得 semid 所表示的信号量集中最后一个使用 semop 函数的进程 ID,即 semid_ds 结构中的 sem.sempid 的值。GETVAL:获得 semid 所表示的信号量集中 semunm 所指定信号量的值。GETZCNT:获得 semid 所表示的信号量集中的等待信号量成为 0 的进程数目,即 semid_ds 结构中的 sem.semncnt 的值。IPC_RMID:删除该信号量。IPC_SET:按参数 arg.buf 指向的结构中的值设置该信号量对应的 semid_ds 结构。只有有效用户 ID 和信号量的所有者 ID 或创建者 ID 相同的用户进程,以及超级用户进程可以执行这一操作。IPC_STAT:获得该信号量的 semid_ds 结构,保存在 arg.buf 指向的缓冲区。SETALL:以 arg.array 中的值设置 semid 所表示的信号量集中信号量的个数。SETVAL:设置 semid 所表示的信号量集中 semnum 所指定信号量的值。

#include <.h> SHMDATASIZE 1000 SN_EMPTY 0 SN_FULL 1 deleteSemid = <span style="color: #0000ff">void server(<span style="color: #0000ff">void<span style="color: #000000">);
<span style="color: #0000ff">void
client(<span style="color: #0000ff">int
shmid,<span style="color: #0000ff">int
<span style="color: #000000"> semid);
<span style="color: #0000ff">void
delete(<span style="color: #0000ff">void
<span style="color: #000000">);
<span style="color: #0000ff">void
sigdelete(<span style="color: #0000ff">int
<span style="color: #000000"> signum);
<span style="color: #0000ff">void locksem(<span style="color: #0000ff">int signum,<span style="color: #0000ff">int<span style="color: #000000"> semnum);
<span style="color: #0000ff">void unlocksem(<span style="color: #0000ff">int semid,<span style="color: #0000ff">int<span style="color: #000000"> semnum);
<span style="color: #0000ff">void clientwrite(<span style="color: #0000ff">int shmid,<span style="color: #0000ff">int semid,<span style="color: #0000ff">char <span style="color: #000000">buffer);
union semun
{
<span style="color: #0000ff">int<span style="color: #000000"> val;
<span style="color: #0000ff">struct semid_ds
<span style="color: #000000">buf;
<span style="color: #0000ff">ushort <span style="color: #000000">array;
};
<span style="color: #0000ff">int safesemget(key_t key,<span style="color: #0000ff">int nssems,<span style="color: #0000ff">int<span style="color: #000000"> semflg);
<span style="color: #0000ff">int safesemctl(<span style="color: #0000ff">int semid,<span style="color: #0000ff">int semunm,<span style="color: #0000ff">int<span style="color: #000000"> cmd,union semun arg);
<span style="color: #0000ff">int safesemop(<span style="color: #0000ff">int semid,<span style="color: #0000ff">struct sembuf
<span style="color: #000000">sops,unsigned nsops);
<span style="color: #0000ff">int safeshmget(key_t key,<span style="color: #0000ff">int size,<span style="color: #0000ff">int<span style="color: #000000"> shmflg);
<span style="color: #0000ff">void safeshmat(<span style="color: #0000ff">int shmid,<span style="color: #0000ff">const <span style="color: #0000ff">void shmaddr,<span style="color: #0000ff">int<span style="color: #000000"> shmflg);
<span style="color: #0000ff">int safeshmctl(<span style="color: #0000ff">int shmid,<span style="color: #0000ff">struct shmid_ds *<span style="color: #000000">buf);

<span style="color: #0000ff">int main(<span style="color: #0000ff">int argc,<span style="color: #0000ff">char *<span style="color: #000000">argv)
{
<span style="color: #0000ff">if(argc < <span style="color: #800080">3<span style="color: #000000">){
server();
}
<span style="color: #0000ff">else<span style="color: #000000">{
client(atoi(argv[<span style="color: #800080">1]),atoi(argv[<span style="color: #800080">2<span style="color: #000000">]));
}
<span style="color: #0000ff">return <span style="color: #800080">0<span style="color: #000000">;
}

<span style="color: #0000ff">void server(<span style="color: #0000ff">void<span style="color: #000000">)
{
union semun sunion;
<span style="color: #0000ff">int<span style="color: #000000"> semid,shmid;
<span style="color: #0000ff">char *<span style="color: #000000">buffer;
semid = safesemget(IPC_PRIVATE,<span style="color: #800080">2,SHM_R|<span style="color: #000000">SHM_W);
deleteSemid =<span style="color: #000000"> semid;
<span style="color: #008000">//<span style="color: #008000"> 在服务器端程序退出时删除掉信号量集。
atexit(&<span style="color: #000000">delete);
signal(SIGINT,&<span style="color: #000000">sigdelete);
<span style="color: #008000">//<span style="color: #008000"> 把第一个信号量设置为 1,第二个信号量设置为 0,<span style="color: #008000">//<span style="color: #008000"> 这样来控制:必须在客户端程序把数据写入共享内存后服务器端程序才能去读共享内存
sunion.val = <span style="color: #800080">1<span style="color: #000000">;
safesemctl(semid,SN_EMPTY,SETVAL,sunion);
sunion.val = <span style="color: #800080">0<span style="color: #000000">;
safesemctl(semid,SN_FULL,sunion);
shmid = safeshmget(IPC_PRIVATE,SHMDATASIZE,IPC_CREAT|SHM_R|<span style="color: #000000">SHM_W);
buffer = safeshmat(shmid,<span style="color: #800080">0,<span style="color: #800080">0<span style="color: #000000">);
safeshmctl(shmid,IPC_RMID,NULL);
<span style="color: #008000">//<span style="color: #008000"> 打印共享内存 ID 和 信号量集 ID,客户端程序需要用它们作为参数
printf(<span style="color: #800000">"<span style="color: #800000">Server is running with SHM id %dn<span style="color: #800000">"<span style="color: #000000">,shmid);
printf(<span style="color: #800000">"<span style="color: #800000">Server is running with SEM id %dn<span style="color: #800000">"<span style="color: #000000">,semid);
<span style="color: #0000ff">while(<span style="color: #800080">1<span style="color: #000000">)
{
printf(<span style="color: #800000">"<span style="color: #800000">Waiting until full...<span style="color: #800000">"<span style="color: #000000">);
fflush(stdout);
locksem(semid,SN_FULL);
printf(<span style="color: #800000">"<span style="color: #800000">done.n<span style="color: #800000">"<span style="color: #000000">);
printf(<span style="color: #800000">"<span style="color: #800000">Message received: %s.n<span style="color: #800000">"<span style="color: #000000">,buffer);
unlocksem(semid,SN_EMPTY);
}
}

<span style="color: #0000ff">void client(<span style="color: #0000ff">int shmid,<span style="color: #0000ff">int<span style="color: #000000"> semid)
{
<span style="color: #0000ff">char *<span style="color: #000000">buffer;
buffer = safeshmat(shmid,<span style="color: #800080">0<span style="color: #000000">);
printf(<span style="color: #800000">"<span style="color: #800000">Client operational: shm id is %d,sem id is %dn<span style="color: #800000">"<span style="color: #000000">,shmid,semid);
<span style="color: #0000ff">while(<span style="color: #800080">1<span style="color: #000000">)
{
<span style="color: #0000ff">char input[<span style="color: #800080">3<span style="color: #000000">];
printf(<span style="color: #800000">"<span style="color: #800000">nnMenun1.Send a messagen<span style="color: #800000">"<span style="color: #000000">);
printf(<span style="color: #800000">"<span style="color: #800000">2.Exitn<span style="color: #800000">"<span style="color: #000000">);
fgets(input,<span style="color: #0000ff">sizeof<span style="color: #000000">(input),stdin);
<span style="color: #0000ff">switch(input[<span style="color: #800080">0<span style="color: #000000">])
{
<span style="color: #0000ff">case <span style="color: #800000">'<span style="color: #800000">1<span style="color: #800000">'<span style="color: #000000">:
clientwrite(shmid,semid,buffer);
<span style="color: #0000ff">break<span style="color: #000000">;
<span style="color: #0000ff">case <span style="color: #800000">'<span style="color: #800000">2<span style="color: #800000">'<span style="color: #000000">:
exit(<span style="color: #800080">0<span style="color: #000000">);
<span style="color: #0000ff">break<span style="color: #000000">;
}
}
}

<span style="color: #0000ff">void locksem(<span style="color: #0000ff">int semid,<span style="color: #0000ff">int<span style="color: #000000"> semnum)
{
<span style="color: #0000ff">struct<span style="color: #000000"> sembuf sb;
sb.sem_num =<span style="color: #000000"> semnum;
sb.sem_op = -<span style="color: #800080">1<span style="color: #000000">;
sb.sem_flg =<span style="color: #000000"> SEM_UNDO;
safesemop(semid,&sb,<span style="color: #800080">1<span style="color: #000000">);
}

<span style="color: #0000ff">void unlocksem(<span style="color: #0000ff">int semid,<span style="color: #0000ff">int<span style="color: #000000"> semnum)
{
<span style="color: #0000ff">struct<span style="color: #000000"> sembuf sb;
sb.sem_num =<span style="color: #000000"> semnum;
sb.sem_op = <span style="color: #800080">1<span style="color: #000000">;
sb.sem_flg =<span style="color: #000000"> SEM_UNDO;
safesemop(semid,<span style="color: #800080">1<span style="color: #000000">);
}

$ -Wall sem.c -o sem_demo

$ ./sem_demo

$ ./sem_demo

$ ipcs -s

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读