wordpress獲取菜單欄優(yōu)化大師好用嗎
概述
什么是信號燈:
信號燈也稱為信號量,代表的是一類資源,其值表示系統(tǒng)中該資源的數(shù)量。
主要用途是實現(xiàn)進程、線程的同步。
什么是P/V操作:
P操作就是申請資源,V操作就是釋放操作。
信號燈的種類:
Posix 有名信號燈:編譯時需鏈接pthread庫。有名信號燈文件存放在/dev/shm目錄下
Posix 無名信號燈:只支持線程同步,編譯時需鏈接pthread庫
System V 信號燈
Posix 信號燈
Posix 信號燈的打開/關閉/刪除函數(shù)有所不同,但PV操作是使用的同一組函數(shù)。具體函數(shù)如下
1、?打開/關閉/刪除
1.1 有名信號燈
//打開
sem_t *sem_open(const char *name,int oflag);
sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
//關閉
int sem_close(sem_t *sem);
//刪除
int sem_unlink(const char *name);
返回值:成功返回信號量指針,失敗返回SEM_FAILED
name:信號燈的名字,即:文件名
oflag:打開方式,常用O_CREAT
mode:文件權限,常用0666
value:信號量值。二元信號燈值為1,普通信號燈表示資源數(shù)目。
1.2 無名信號燈
//創(chuàng)建
int sem_init(sem_t *sem, int pshared, unsigned int value);
//銷毀
int sem_destroy(sem_t *sem);
sem:信號量指針
pshared:寫0,代表不能在進程間共享。Linux中無名信號燈不能在進程間通信
value:信號量值。
2、P/V操作
2.1 P操作
int sem_wait(sem_t *sem);
當信號量為0時,進入阻塞,直到信號量不為0
當信號量不為0時,會將信號量的值-1
2.2?V操作
int sem_post(sem_t *sem);
該函數(shù)使用后會將信號量值+1
System V?信號燈
1、創(chuàng)建
int semget(key_t key, int nsems, int semflg);
返回值:成功返回信號燈id,失敗返回-1
key:鍵值,由ftok生成
nsems:信號燈的個數(shù)
semflg:權限,通常寫為IPC_CREAT|0666
2、控制信號燈
int semctl(int semid, int semnum, int cmd, ...);
semid:信號燈id
semnum:操作哪一個信號燈,序號從0開始
cmd:寫入IPC_RMID,代表刪除操作
? ? ? ? ? ?寫入SETVAL,代表初始化信號燈的值,此時需要傳入第四個參數(shù),類型是共用體
union semun共用體:
union semun {int val; //設置信號燈的初始值struct semid_ds *buf;unsigned short *array;
} arg;
3、P/V操作
int semop(int semid, struct sembuf *sops, size_t nsops);
semid:信號燈id
sops:P/V操作
nsops:要操作的信號燈個數(shù),通常寫1
struct sembuf結構體:
struct sembuf {unsigned short sem_num; //要操作的信號燈的編號short sem_op; //1:V操作,-1:P操作short sem_flg; //0:阻塞,IPC_NOWAIT不阻塞
};
示例代碼
1、有名信號燈
見博文"12.2 Linux_進程間通信_共享內存"-"相關函數(shù)"-"實驗代碼"-"2、AB進程互傳數(shù)據(jù)"
博文鏈接為:12.2 Linux_進程間通信_共享內存-CSDN博客
2、無名信號燈
無名信號燈只能用于線程間通信,下面是無名信號燈實現(xiàn)AB線程利用共享內存互傳數(shù)據(jù)。
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>sem_t sem_mmap;
void* mmap_addr = NULL;
char buf[100] = {0};
int i=0;
void* Afun(void* arg){memcpy(mmap_addr,"A Start SIG",strlen("A Start SIG"));while(1){sem_wait(&sem_mmap);if(*(char*)mmap_addr == 'B'){//讀出B線程寫入的內容printf("A read:%s\n",(char*)mmap_addr+strlen("B"));//讀取數(shù)據(jù),不讀取數(shù)據(jù)來源標號memset(mmap_addr,0,strlen(mmap_addr));//清空緩沖區(qū)//寫入新數(shù)據(jù)memcpy(mmap_addr,"A",strlen("A"));//數(shù)據(jù)來源標號sprintf(buf,"A_Data:%d",i++); //新數(shù)據(jù)memcpy(mmap_addr+strlen("A"),buf,strlen(buf));}sem_post(&sem_mmap);}
}
void* Bfun(void* arg){while(1){sem_wait(&sem_mmap);if(*(char*)mmap_addr == 'A'){//讀出A線程寫入的內容printf("B read:%s\n",(char*)mmap_addr+strlen("A"));memset(mmap_addr,0,strlen(mmap_addr));//清空緩沖區(qū)//寫入新數(shù)據(jù)memcpy(mmap_addr,"B",strlen("B"));//數(shù)據(jù)來源標號sprintf(buf,"B get A data,B data is %d",i++); //新數(shù)據(jù)memcpy(mmap_addr+strlen("B"),buf,strlen(buf));sleep(1);}sem_post(&sem_mmap);}
}#define FILE_PATH "./mmap"
int main(){pthread_t tid[2];int fd;//打開文件if((fd=open(FILE_PATH,O_RDWR)) < 0){perror("open");return -1;}//創(chuàng)建共享內存映射if((mmap_addr = mmap(NULL,4*1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){perror("mmap");return -1;}memset(mmap_addr,lseek(fd,0,SEEK_END),strlen(mmap_addr));//清空緩沖區(qū)close(fd);//創(chuàng)建共享內存映射后可以關閉文件描述符//創(chuàng)建信號量sem_init(&sem_mmap,0,1);//創(chuàng)建線程pthread_create(&tid[0],NULL,Afun,NULL);pthread_create(&tid[1],NULL,Bfun,NULL);while(1);return 0;
}
3、System V信號燈
使用SystemV信號燈實現(xiàn)"有名信號燈"章節(jié)的同樣功能
A.c代碼如下:
#include <sys/sem.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define FILE_PATH "./mmap"
union semun {int val; //設置信號燈的初始值struct semid_ds *buf;unsigned short *array;
} arg;
int main(){int fd;void* mmap_addr = NULL;int i=0;char buf[100] = {0};key_t key;int sem_mmap;struct sembuf semPV;//打開文件if((fd=open(FILE_PATH,O_RDWR)) < 0){perror("open");return -1;}//創(chuàng)建共享內存映射if((mmap_addr = mmap(NULL,4*1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){perror("mmap");return -1;}memset(mmap_addr,0,lseek(fd,0,SEEK_END));//清空緩沖區(qū)close(fd);//創(chuàng)建共享內存映射后可以關閉文件描述符//創(chuàng)建信號量key = ftok(".",1);if((sem_mmap = semget(key,1,IPC_CREAT|0666)) == -1){perror("sem_get");return -1;}arg.val = 1;semctl(sem_mmap,0,SETVAL,arg);//進程間通信memcpy(mmap_addr,"A Start SIG",strlen("A Start SIG"));while(1){semPV.sem_num = 0;semPV.sem_op=-1;semPV.sem_flg=0;semop(sem_mmap,&semPV,1);if(*(char*)mmap_addr == 'B'){//讀出B進程寫入的內容printf("A read:%s\n",(char*)mmap_addr+strlen("B"));//讀取數(shù)據(jù),不讀取數(shù)據(jù)來源標號memset(mmap_addr,0,strlen(mmap_addr));//清空緩沖區(qū)//寫入新數(shù)據(jù)memcpy(mmap_addr,"A",strlen("A"));//數(shù)據(jù)來源標號sprintf(buf,"A_Data:%d",i++); //新數(shù)據(jù)memcpy(mmap_addr+strlen("A"),buf,strlen(buf));}semPV.sem_num = 0;semPV.sem_op=1;semPV.sem_flg=0;semop(sem_mmap,&semPV,1);}return 0;
}
B.c的代碼如下:
#include <sys/mman.h>
#include <sys/sem.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define FILE_PATH "./mmap"
union semun {int val; //設置信號燈的初始值struct semid_ds *buf;unsigned short *array;
} arg;
int main(){int fd;void* mmap_addr = NULL;int i=0;char buf[100] = {0};key_t key;int sem_mmap;struct sembuf semPV;//打開文件if((fd=open(FILE_PATH,O_RDWR)) < 0){perror("open");return -1;}//創(chuàng)建共享內存映射if((mmap_addr = mmap(NULL,4*1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){perror("mmap");return -1;}memset(mmap_addr,0,lseek(fd,0,SEEK_END));//清空緩沖區(qū)close(fd);//創(chuàng)建共享內存映射后可以關閉文件描述符//創(chuàng)建信號量key = ftok(".",1);if((sem_mmap = semget(key,1,IPC_CREAT|0666)) == -1){perror("sem_get");return -1;}arg.val = 1;semctl(sem_mmap,0,SETVAL,arg);//進程間通信while(1){semPV.sem_num = 0;semPV.sem_op=-1;semPV.sem_flg=0;semop(sem_mmap,&semPV,1);if(*(char*)mmap_addr == 'A'){//讀出A進程寫入的內容printf("B read:%s\n",(char*)mmap_addr+strlen("A"));memset(mmap_addr,0,strlen(mmap_addr));//清空緩沖區(qū)//寫入新數(shù)據(jù)memcpy(mmap_addr,"B",strlen("B"));//數(shù)據(jù)來源標號sprintf(buf,"B get A data,B data is %d",i++); //新數(shù)據(jù)memcpy(mmap_addr+strlen("B"),buf,strlen(buf));sleep(1);}semPV.sem_num = 0;semPV.sem_op=1;semPV.sem_flg=0;semop(sem_mmap,&semPV,1);}return 0;
}