中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

swoole中信號量怎么使用

發布時間:2022-03-14 15:37:17 來源:億速云 閱讀:137 作者:iii 欄目:編程語言

這篇文章主要介紹了swoole中信號量怎么使用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇swoole中信號量怎么使用文章都會有所收獲,下面我們一起來看看吧。

在swoole中,信號量主要用來保護共享資源,使得資源在一個時刻只有一個進程;信號量的值為正的時候,說明所測試的線程可以鎖定而使用,信號量的值若為0,則說明測試的線程要進入睡眠隊列中,等待被喚醒。

本教程操作環境:Windows10系統、Swoole4版、DELL G3電腦

swoole中信號量的用法

信號量的使用主要是用來保護共享資源,使得資源在一個時刻只有一個進程(線程)

所擁有。信號量的值為正的時候,說明它空閑。所測試的線程可以鎖定而使用它。若為0,說明它被占用,測試的線程要進入睡眠隊列中,等待被喚醒。

Linux提供兩種信號量:

(1) 內核信號量,由內核控制路徑使用

(2) 用戶態進程使用的信號量,這種信號量又分為POSIX信號量和SYSTEM

V信號量。

POSIX信號量又分為有名信號量和無名信號量。

有名信號量,其值保存在文件中, 所以它可以用于線程也可以用于進程間的同步。無名

信號量,其值保存在內存中。

內核信號量

內核信號量的構成

內核信號量類似于自旋鎖,因為當鎖關閉著時,它不允許內核控制路徑繼續進行。然而,

當內核控制路徑試圖獲取內核信號量鎖保護的忙資源時,相應的進程就被掛起。只有在資源被釋放時,進程才再次變為可運行。

只有可以睡眠的函數才能獲取內核信號量;中斷處理程序和可延遲函數都不能使用內

核信號量。

內核信號量是struct semaphore類型的對象,它在

#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int number; // 被保護的全局變量
sem_t sem_id;
void* thread_one_fun(void *arg)
{
sem_wait(&sem_id);
printf("thread_one have the semaphore\n");
number++;
printf("number = %d\n",number);
sem_post(&sem_id);
}
void* thread_two_fun(void *arg)
{
sem_wait(&sem_id);
printf("thread_two have the semaphore \n");
number--;
printf("number = %d\n",number);
sem_post(&sem_id);
}
int main(int argc,char *argv[])
{
number = 1;
pthread_t id1, id2;
sem_init(&sem_id, 0, 1);
pthread_create(&id1,NULL,thread_one_fun, NULL);
pthread_create(&id2,NULL,thread_two_fun, NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
printf("main,,,\n");
return 0;
}

上面的例程,到底哪個線程先申請到信號量資源,這是隨機的。如果想要某個特定的順

序的話,可以用2個信號量來實現。例如下面的例程是線程1先執行完,然后線程2才繼

續執行,直至結束。

int number; // 被保護的全局變量
sem_t sem_id1, sem_id2;
void* thread_one_fun(void *arg)
{
sem_wait(&sem_id1);
printf(“thread_one have the semaphore\n”);
number++;
printf(“number = %d\n”,number);
sem_post(&sem_id2);
}
void* thread_two_fun(void *arg)
{
sem_wait(&sem_id2);
printf(“thread_two have the semaphore \n”);
number–;
printf(“number = %d\n”,number);
sem_post(&sem_id1);
}
int main(int argc,char *argv[])
{
number = 1;
pthread_t id1, id2;
sem_init(&sem_id1, 0, 1); // 空閑的
sem_init(&sem_id2, 0, 0); // 忙的
pthread_create(&id1,NULL,thread_one_fun, NULL);
pthread_create(&id2,NULL,thread_two_fun, NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
printf(“main,,,\n”);
return 0;
}

(b)無名信號量在相關進程間的同步

說是相關進程,是因為本程序中共有2個進程,其中一個是另外一個的子進程(由

fork

產生)的。

本來對于fork來說,子進程只繼承了父進程的代碼副本,mutex理應在父子進程

中是相互獨立的兩個變量,但由于在初始化mutex的時候,由pshared = 1指

定了mutex處于共享內存區域,所以此時mutex變成了父子進程共享的一個變

量。此時,mutex就可以用來同步相關進程了。

#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
int fd, i,count=0,nloop=10,zero=0,*ptr;
sem_t mutex;
//open a file and map it into memory
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);
write(fd,&zero,sizeof(int));
ptr = mmap( NULL,sizeof(int),PROT_READ |
PROT_WRITE,MAP_SHARED,fd,0 );
close(fd);
/* create, initialize semaphore */
if( sem_init(&mutex,1,1) < 0) //
{
perror("semaphore initilization");
exit(0);
}
if (fork() == 0)
{ /* child process*/
for (i = 0; i < nloop; i++)
{
sem_wait(&mutex);
printf("child: %d\n", (*ptr)++);
sem_post(&mutex);
}
exit(0);
}
/* back to parent process */
for (i = 0; i < nloop; i++)
{
sem_wait(&mutex);
printf("parent: %d\n", (*ptr)++);
sem_post(&mutex);
}
exit(0);
}

2.有名信號量

有名信號量的特點是把信號量的值保存在文件中。

這決定了它的用途非常廣:既可以用于線程,也可以用于相關進程間,甚至是不相關

進程。

(a)有名信號量能在進程間共享的原因

由于有名信號量的值是保存在文件中的,所以對于相關進程來說,子進程是繼承了父

進程的文件描述符,那么子進程所繼承的文件描述符所指向的文件是和父進程一樣的,當

然文件里面保存的有名信號量值就共享了。

(b)有名信號量相關函數說明

有名信號量在使用的時候,和無名信號量共享sem_wait和sem_post函數。

區別是有名信號量使用sem_open代替sem_init,另外在結束的時候要像關閉文件

一樣去關閉這個有名信號量。

(1)打開一個已存在的有名信號量,或創建并初始化一個有名信號量。一個單一的調用就完

成了信號量的創建、初始化和權限的設置。

sem_t *sem_open(const char *name, int oflag, mode_t mode , int value);

name是文件的路徑名;

Oflag 有O_CREAT或O_CREAT|EXCL兩個取值;

mode_t控制新的信號量的訪問權限;

Value指定信號量的初始化值。

注意:

這里的name不能寫成/tmp/aaa.sem這樣的格式,因為在linux下,sem都是創建

在/dev/shm目錄下。你可以將name寫成“/mysem”或“mysem”,創建出來的文件都

是“/dev/shm/sem.mysem”,千萬不要寫路徑。也千萬不要寫“/tmp/mysem”之類的。

當oflag = O_CREAT時,若name指定的信號量不存在時,則會創建一個,而且后

面的mode和value參數必須有效。若name指定的信號量已存在,則直接打開該信號量,

同時忽略mode和value參數。

當oflag = O_CREAT|O_EXCL時,若name指定的信號量已存在,該函數會直接返

回error。

(2) 一旦你使用了信號量,銷毀它們就變得很重要。

在做這個之前,要確定所有對這個有名信號量的引用都已經通過sem_close()函數

關閉了,然后只需在退出或是退出處理函數中調用sem_unlink()去刪除系統中的信號量,

注意如果有任何的處理器或是線程引用這個信號量,sem_unlink()函數不會起到任何的作

用。

也就是說,必須是最后一個使用該信號量的進程來執行sem_unlick才有效。因為每個

信號燈有一個引用計數器記錄當前的打開次數,sem_unlink必須等待這個數為0時才能把

name所指的信號燈從文件系統中刪除。也就是要等待最后一個sem_close發生。

(c)有名信號量在無相關進程間的同步

前面已經說過,有名信號量是位于共享內存區的,那么它要保護的資源也必須是位于

共享內存區,只有這樣才能被無相關的進程所共享。

在下面這個例子中,服務進程和客戶進程都使用shmget和shmat來獲取得一塊共享內

存資源。然后利用有名信號量來對這塊共享內存資源進行互斥保護。

File1: server.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
//name the shared memory segment
key = 1000;
//create & initialize semaphore
mutex = sem_open(SEM_NAME,O_CREAT,0644,1);
if(mutex == SEM_FAILED)
{
perror("unable to create semaphore");
sem_unlink(SEM_NAME);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,IPC_CREAT|0666);
if(shmid<0)
{
perror("failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0);
//start writing into memory
s = shm;
for(ch='A';ch<='Z';ch++)
{
sem_wait(mutex);
*s++ = ch;
sem_post(mutex);
}
//the below loop could be replaced by binary semaphore
while(*shm != '*')
{
sleep(1);
}
sem_close(mutex);
sem_unlink(SEM_NAME);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}
<u>File 2: client.c</u>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
//name the shared memory segment
key = 1000;
//create & initialize existing semaphore
mutex = sem_open(SEM_NAME,0,0644,0);
if(mutex == SEM_FAILED)
{
perror("reader:unable to execute semaphore");
sem_close(mutex);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,0666);
if(shmid<0)
{
perror("reader:failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0);
//start reading
s = shm;
for(s=shm;*s!=NULL;s++)
{
sem_wait(mutex);
putchar(*s);
sem_post(mutex);
}
//once done signal exiting of reader:This can be replaced by
another semaphore
*shm = '*';
sem_close(mutex);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}

SYSTEM V信號量

這是信號量值的集合,而不是單個信號量。相關的信號量操作函數由

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
static int nsems;
static int semflg;
static int semid;
int errno=0;
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
int main()
{
struct sembuf sops[2]; //要用到兩個信號量,所以要定義兩個操作數組
int rslt;
unsigned short argarray[80];
arg.array = argarray;
semid = semget(IPC_PRIVATE, 2, 0666);
if(semid < 0 )
{
printf("semget failed. errno: %d\n", errno);
exit(0);
}
//獲取0th信號量的原始值
rslt = semctl(semid, 0, GETVAL);
printf("val = %d\n",rslt);
//初始化0th信號量,然后再讀取,檢查初始化有沒有成功
arg.val = 1; // 同一時間只允許一個占有者
semctl(semid, 0, SETVAL, arg);
rslt = semctl(semid, 0, GETVAL);
printf("val = %d\n",rslt);
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1;
sops[1].sem_flg = 0;
rslt=semop(semid, sops, 1); //申請0th信號量,嘗試鎖定
if (rslt < 0 )
{
printf("semop failed. errno: %d\n", errno);
exit(0);
}
//可以在這里對資源進行鎖定
sops[0].sem_op = 1;
semop(semid, sops, 1); //釋放0th信號量
rslt = semctl(semid, 0, GETVAL);
printf("val = %d\n",rslt);
rslt=semctl(semid, 0, GETALL, arg);
if (rslt < 0)
{
printf("semctl failed. errno: %d\n", errno);
exit(0);
}
printf("val1:%d val2: %d\n",(unsigned int)argarray[0],(unsigned int)argarray[1]);
if(semctl(semid, 1, IPC_RMID) == -1)
{
Perror(“semctl failure while clearing reason”);
}
return(0);
}

關于“swoole中信號量怎么使用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“swoole中信號量怎么使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

民勤县| 博野县| 久治县| 锦州市| 瑞金市| 铜陵市| 滕州市| 封丘县| 宁津县| 珠海市| 广州市| 海安县| 昌平区| 襄汾县| 汶川县| 珠海市| 察哈| 四川省| 锦屏县| 临朐县| 铜梁县| 怀远县| 沙湾县| 太和县| 洱源县| 张家口市| 苍溪县| 喀喇| 牙克石市| 会同县| 六枝特区| 迁安市| 林西县| 保定市| 屏南县| 临湘市| 凭祥市| 岑溪市| 沾益县| 天峨县| 崇义县|