導航:首頁 > 網路營銷 > sem多元信號量

sem多元信號量

發布時間:2020-10-24 20:05:42

1、在ucos中創建一個信號量 比如ossemcreat(0)。ossemcreat(1)的區別

OSSemPost 和OSSemPend是成對出現的,在程序OSSemPost 尚未運行到的時候,在等待Sem的
OSSemPend是會把當前的任務掛起,直到另外一個任務的OSSemPost 運行完畢都得到Sem。但是可以通過改變OSSemCreate(x)裡面的值x改變這種局面,當x不為0時,OSSemPend會馬上得到Sem繼續運行當前任務至結束,並將x的數值減一,直到為0。為0後,只有等其他任務的OSSemPost了。

2、關於linux下的多線程使用sem信號量的運行問題

不是信號量的問題
printf函數,是先寫到輸出緩沖,遇到\n時,或者緩沖區滿時,或者有強制輸出(fflush)時,才會將緩沖區里的內容輸出到屏幕上(標准輸出設備:stdout)。你的代碼裡面並沒有以上3個觸發條件的任意一種,所以printf的內存沒有實際輸出到屏幕上。
你只要在每個printf函數後面加上fflush(stdout);就可以了。

3、信號量的使用,求助

信號量:一個整數;
大於或等於0時代表可供並發進程使用的資源實體數;
小於0時代表正在等待使用臨界區的進程數;
用於互斥的信號量初始值應大於0;
只能通過P、V原語操作而改變;
信號量元素組成:
1、表示信號量元素的值;
2、最後操作信號量元素的進程ID
3、等待信號量元素值+1的進程數;
4、等待信號量元素值為0的進程數;

二、主要函數

1.1 創建信號量
int semget(
key_t key, //標識信號量的關鍵字,有三種方法:1、使用IPC——PRIVATE讓系統產生,
// 2、挑選一個隨機數,3、使用ftok從文件路徑名中產生
int nSemes, //信號量集中元素個數
int flag //IPC_CREAT;IPC_EXCL 只有在信號量集不存在時創建
)
成功:返回信號量句柄
失敗:返回-1

1.2 使用ftok函數根據文件路徑名產生一個關鍵字
key_t ftok(const char *pathname,int proj_id);
路徑名稱必須有相應許可權

1.3 控制信號量
int semctl(
int semid, //信號量集的句柄
int semnum, //信號量集的元素數
int cmd, //命令
/*union senum arg */... //
)
成功:返回相應的值
失敗:返回-1

命令詳細說明:
cmd: IPC_RMID 刪除一個信號量
IPC_EXCL 只有在信號量集不存在時創建
IPC_SET 設置信號量的許可權
SETVAL 設置指定信號量的元素的值為 agc.val
GETVAL 獲得一個指定信號量的值
GETPID 獲得最後操縱此元素的最後進程ID
GETNCNT 獲得等待元素變為1的進程數
GETZCNT 獲得等待元素變為0的進程數

union senum 定義如下:
union senum{
int val;
struct semid_ds *buf;
unsigned short * array;
}agc;
其中 semid_ds 定義如下:
struct semid_ds{
struct ipc_pem sem_pem; //operation pemission struct
time_t sem_otime; //last semop()time
time_t sem_ctime; //last time changed by semctl()
struct sem *sembase; //ptr to first semaphore in array
struct sem_queue *sem_pending; //pending operations
struct sem_queue *sem_pending_last; //last pending operations
struct sem_undo *undo; //undo requests on this arrary
unsigned short int sem_nsems; //number of semaphores in set
};

1.4 對信號量 +1 或 -1 或測試是否為0
int semop(
int semid,
struct sembuf *sops, //指向元素操作數組
unsigned short nsops //數組中元素操作的個數
)

結構 sembuf 定義
sembuf{
short int sem_num; //semaphore number
short int sem_op; //semaphore operaion
short int sem_flg //operation flag
};

三、例子:
2.1 伺服器

#include <sys/sem.h>
#include <sys/ipc.h>

#define SEGSIZE 1024
#define READTIME 1
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;
//生成信號量
int sem_creat(key_t key)
{
union semun sem;
int semid;
sem.val = 0;
semid = semget(key,1,IPC_CREAT|0666);
if (-1 == semid){
printf("create semaphore error\n");
exit(-1);
}
semctl(semid,0,SETVAL,sem);
return semid;
}
//刪除信號量
void del_sem(int semid)
{
union semun sem;
sem.val = 0;
semctl(semid,0,IPC_RMID,sem);
}

//p
int p(int semid)
{
struct sembuf sops={0,+1,IPC_NOWAIT};
return (semop(semid,&sops,1));
}
//v
int v(int semid)
{
struct sembuf sops={0,-1,IPC_NOWAIT};
return (semop(semid,&sops,1));
}
int main()
{
key_t key;
int shmid,semid;
char *shm;
char msg[7] = "-data-";
char i;
struct semid_ds buf;

key = ftok("/",0);
shmid = shmget(key,SEGSIZE,IPC_CREAT|0604);
if (-1 == shmid){
printf(" create shared memory error\n");
return -1;
}
shm = (char *)shmat(shmid,0,0);
if (-1 == (int)shm){
printf(" attach shared memory error\n");
return -1;
}
semid = sem_creat(key);
for (i = 0;i <= 3;i++){
sleep(1);
p(semid);
sleep(READTIME);
msg[5] = '0' + i;
memcpy(shm,msg,sizeof(msg));
sleep(58);
v(semid);
}
shmdt(shm);
shmctl(shmid,IPC_RMID,&buf);
del_sem(semid);
return 0;
//gcc -o shm shm.c -g
}

2.2 客戶端

#include <sys/sem.h>
#include <time.h>
#include <sys/ipc.h>

#define SEGSIZE 1024
#define READTIME 1
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;

// 列印程序執行時間
void out_time(void)
{
static long start = 0;
time_t tm;
if (0 == start){
tm = time(NULL);
start = (long)tm;
printf(" now start ...\n");
}
printf(" second: %ld \n",(long)(time(NULL)) - start);
}

//創建信號量
int new_sem(key_t key)
{
union semun sem;
int semid;
sem.val = 0;
semid = semget(key,0,0);
if (-1 == semid){
printf("create semaphore error\n");
exit(-1);
}
return semid;
}

//等待信號量變成0
void wait_v(int semid)
{
struct sembuf sops={0,0,0};
semop(semid,&sops,1);
}

int main(void)
{
key_t key;
int shmid,semid;
char *shm;
char msg[100];
char i;

key = ftok("/",0);
shmid = shmget(key,SEGSIZE,0);

if(-1 == shmid){
printf(" create shared memory error\n");
return -1;
}
shm = (char *)shmat(shmid,0,0);
if (-1 == (int)shm){
printf(" attach shared memory error\n");
return -1;
}
semid = new_sem(key);
for (i = 0;i < 3;i ++){
sleep(2);
wait_v(semid);
printf("Message geted is: %s \n",shm + 1);
out_time();
}
shmdt(shm);
return 0;
// gcc -o shmc shmC.c -g
}

4、linux 信號量操作函數

semget()
可以使用系統調用semget()創建一個新的信號量集,或者存取一個已經存在的信號量集:
系統調用:semget();
原型:intsemget(key_t key,int nsems,int semflg);
返回值:如果成功,則返回信號量集的IPC標識符。如果失敗,則返回-1:errno=EACCESS(沒有許可權)
EEXIST(信號量集已經存在,無法創建)
EIDRM(信號量集已經刪除)
ENOENT(信號量集不存在,同時沒有使用IPC_CREAT)
ENOMEM(沒有足夠的內存創建新的信號量集)
ENOSPC(超出限制)
系統調用semget()的第一個參數是關鍵字值(一般是由系統調用ftok()返回的)。系統內核將此值和系統中存在的其他的信號量集的關鍵字值進行比 較。打開和存取操作與參數semflg中的內容相關。IPC_CREAT如果信號量集在系統內核中不存在,則創建信號量集。IPC_EXCL當和 IPC_CREAT一同使用時,如果信號量集已經存在,則調用失敗。如果單獨使用IPC_CREAT,則semget()要麼返回新創建的信號量集的標識 符,要麼返回系統中已經存在的同樣的關鍵字值的信號量的標識符。如果IPC_EXCL和IPC_CREAT一同使用,則要麼返回新創建的信號量集的標識 符,要麼返回-1。IPC_EXCL單獨使用沒有意義。參數nsems指出了一個新的信號量集中應該創建的信號量的個數。信號量集中最多的信號量的個數是 在linux/sem.h中定義的:
#defineSEMMSL32/*<=512maxnumofsemaphoresperid*/
下面是一個打開和創建信號量集的程序:
intopen_semaphore_set(key_t keyval,int numsems)
{
intsid;
if(!numsems)
return(-1);
if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1)
{
return(-1);
}
return(sid);
}
};
==============================================================
semop()
系統調用:semop();
調用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
返回值:0,如果成功。-1,如果失敗:errno=E2BIG(nsops大於最大的ops數目)
EACCESS(許可權不夠)
EAGAIN(使用了IPC_NOWAIT,但操作不能繼續進行)
EFAULT(sops指向的地址無效)
EIDRM(信號量集已經刪除)
EINTR(當睡眠時接收到其他信號)
EINVAL(信號量集不存在,或者semid無效)
ENOMEM(使用了SEM_UNDO,但無足夠的內存創建所需的數據結構)
ERANGE(信號量值超出范圍)
第一個參數是關鍵字值。第二個參數是指向將要操作的數組的指針。第三個參數是數組中的操作的個數。參數sops指向由sembuf組成的數組。此數組是在linux/sem.h中定義的:
/*semop systemcall takes an array of these*/
structsembuf{
ushortsem_num;/*semaphore index in array*/
shortsem_op;/*semaphore operation*/
shortsem_flg;/*operation flags*/
sem_num將要處理的信號量的個數。
sem_op要執行的操作。
sem_flg操作標志。
如果sem_op是負數,那麼信號量將減去它的值。這和信號量控制的資源有關。如果沒有使用IPC_NOWAIT,那麼調用進程將進入睡眠狀態,直到信號 量控制的資源可以使用為止。如果sem_op是正數,則信號量加上它的值。這也就是進程釋放信號量控制的資源。最後,如果sem_op是0,那麼調用進程 將調用sleep(),直到信號量的值為0。這在一個進程等待完全空閑的資源時使用。

5、多線程編程的原則以及Sem信號量和Mutex互斥鎖的區別

以下兩種類型:
二值信號量:最簡單的信號量形式,信號量的值只能取0或1,類似於互斥鎖。
註:二值信號量能夠實現互斥鎖的功能,但兩者的關注內容不同。信號量強調共享資源,只要共享資源可用,其他進程同樣可以修改信號量的值;互斥鎖更強調進程,佔用資源的進程使用完資源後,必須由進

6、計算機*作系統中,若P、V*作的信號量S初值為2,當前值為-1,則表示有____個等待進程

有1個等待進程。

信號量(Semaphore),是可以用來保證兩個或多個關鍵代碼段不被並發調用。在進入一個關鍵代碼段之前,線程必須獲取一個信號量;一旦該關鍵代碼段完成了,那麼該線程必須釋放信號量。其它想進入該關鍵代碼段的線程必須等待直到第一個線程釋放信號量。

為了完成這個過程,需要創建一個信號量VI,然後將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個關鍵代碼段的首末端。初值為2,表示初始時有兩個可用的資源。現在為-1,就說明這兩個可用資源已經被佔用了,有一個進程還在等待資源。

(6)sem多元信號量擴展資料:

對信號量有4種操作(#include<semaphore.h>):

1、 初始化(initialize),也叫做建立(create) int sem_init(sem_t *sem, int pshared, unsigned int value);

2、等信號(wait),也可叫做掛起(suspend)int sem_wait(sem_t *sem);

3、給信號(signal)或發信號(post) int sem_post(sem_t *sem);

4、清理(destroy) int sem_destory(sem_t *sem)。

7、linux信號量的問題

sem_init:初始化信號量sem_t,初始化的時候可以指定信號量的初始值,以及是否可以在多進程間共享。
sem_wait:一直阻塞等待直到信號量>0。
sem_timedwait:阻塞等待若干時間直到信號量>0。
sem_post:使信號量加1。
sem_destroy:釋放信號量。和sem_init對應。 答案補充 關於各函數的具體參數請用man查看,如man sem_init可查看該函數的幫助

與sem多元信號量相關的知識