?? sem.c
字號:
/**********************************************************************
*FileName: sem.c
*
*Perpose : 通過信號量來同步進程,讓兩個進程分別輸出aaa bbb.
* 直到用戶按下Ctrl+C.這個程序的功能類似于Linus在
* 開始寫Linux時寫的第一個版本.不過Linux是在保護模
* 式下,通過時鐘中斷來實現的.這個程序只是通過操作系
* 統提供的system call來實現.所以很簡單!!!
*
*Author : 劉海洋
*Version : 2008-11-08 第一版
*
*Addition: 這里創建了一個信號量集,這個信號量集包含了一個信號量
* 并且信號量的最大值為1, 所以這里的信號量可以理解為互斥體
**********************************************************************/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#define SEMPERM 0600 /* 八進制,所以前面的0不能省略 */
typedef union _semun
{
int val;
struct semid_ds *buf;
ushort *array;
}semun;
/*
===============
初始化信號量
===============
*/
int initsem(key_t semkey)
{
int status = 0;
int semid;
/* 試著創建一個信號量 */
semid = semget(semkey, 1, SEMPERM | IPC_CREAT | IPC_EXCL);
if (semid == -1) /* 創建失敗 */
{
if (errno == EEXIST) /* 如果存在,試著獲取它 */
{
semid = semget(semkey, 1, 0);
}
}
else /* 創建成功,則給信號量賦初值 */
{
semun arg;
arg.val = 1;
status == semctl(semid, 0, SETVAL, arg);
}
if (semid == -1 || status == -1)
{
perror("init semaphore failed!\n");
exit(-1);
}
return semid;
}
/*
=============
信號量P操作
=============
*/
int p(int semid)
{
struct sembuf p_buf;
p_buf.sem_num = 0;
p_buf.sem_op = -1;
p_buf.sem_flg = SEM_UNDO;
if (semop(semid, &p_buf, 1) == -1)
{
perror("semaphore p operation failed\n");
exit(-1);
}
return 0;
}
/*
=============
信號量v操作
=============
*/
int v(int semid)
{
struct sembuf p_buf;
p_buf.sem_num = 0;
p_buf.sem_op = 1;
p_buf.sem_flg = SEM_UNDO;
if (semop(semid, &p_buf, 1) == -1)
{
perror("semaphore v operation failed\n");
exit(-1);
}
return 0;
}
/*
=============
刪除信號量
=============
*/
int rmsem(int semid)
{
semun sem;
sem.val = 0;
if (semctl(semid, 0, IPC_RMID, sem) == -1)
{
perror("remove semaphore failed\n");
exit(-1);
}
return 0;
}
/*
========================
通過信號量同步循環輸出
========================
*/
int printbysem(int semid, char *str)
{
while (1)
{
p(semid); /* Note */
printf("%s", str);
sleep(1);
v(semid); /* Note */
sleep(1);
}
return 0;
}
/*
==================================
在sigint中刪除信號量時,需要指定ID
==================================
*/
int g_sem_id = 0;
/*
==============
中斷信號處理
==============
*/
void sigint(int signo)
{
rmsem(g_sem_id);
printf("\n");
exit(0);
}
/*
===============
Program Entry
===============
*/
int main(void)
{
key_t sem_key = 0x200;
int semid;
setbuf(stdout, NULL); /* 設置輸入輸出緩沖為無緩沖 */
switch (fork())
{
case -1: /* error */
perror("create new process failed!\n");
break;
case 0: /* child process */
semid = initsem(sem_key);
printbysem(semid, "aaa");
break;
default: /* perant process */
g_sem_id = semid = initsem(sem_key);
signal(SIGINT, sigint); /* 只有父進程注冊信號處理函數 */
printbysem(semid, "bbb");
break;
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -