日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux IPC实践(11) --System V信号量(1)

發布時間:2025/3/17 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux IPC实践(11) --System V信号量(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

信號量API

#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); int semctl(int semid, int semnum, int cmd, ...); int semop(int semid, struct sembuf *sops, unsigned nsops);

semget

int semget(key_t key, int nsems, int semflg);

創建/訪問一個信號量集

參數:

? ?key:?信號集鍵(key)

? ?nsems:信號集中信號量的個數

? ?semflg:?由九個權限標志構成,它們的用法和創建文件時使用的mode模式標志一致

返回值:成功返回一個非負整數,即該信號集的標識碼;失敗返回-1;

? ?此時創建的信號量集中的每一個信號量都會有一個默認值:?0,?如果需要更改該值,?則需要調用semctl函數->更改初始值;

/** 示例1: 封裝一個創建一個信號量集函數 該信號量集包含1個信號量; 權限為0666 **/ int sem_create(key_t key) {int semid = semget(key, 1, IPC_CREAT|IPC_EXCL|0666);if (semid == -1)err_exit("sem_create error");return semid; } /** 示例2: 打開一個信號量集 nsems(信號量數量)可以填0, semflg(信號量權限)也可以填0, 表示使用默認的權限打開 **/ int sem_open(key_t key) {int semid = semget(key, 0, 0);if (semid == -1)err_exit("sem_open error");return semid; }

shmctl

int semctl(int semid, int semnum, int cmd, ...);

控制信號量集

參數

? ?semid:由semget返回的信號集標識碼

? ?semnum:信號集中信號量的序號(注意:?從0開始The?semaphores?in?a?set?are?numbered?starting?at?0.)

? ?cmd:將要采取的動作(常用取值如下)


? ?如果該函數需要第四個參數(有時是不需要第四個參數的,?取決于cmd的取值),?則程序中必須定義如下的聯合體:

union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific)*/ }; //struct semid_ds : Linux內核為System V信號量維護的數據結構 struct semid_ds {struct ipc_perm sem_perm; /* Ownership and permissions */time_t sem_otime; /* Last semop time */time_t sem_ctime; /* Last change time */unsigned long sem_nsems; /* No. of semaphores in set */ }; /** 示例1: 將信號量集semid中的第一個信號量的值設置成為value(SETVAL) 注意: semun聯合體需要自己給出(從man-page中拷貝出來即可) **/ union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */ }; int sem_setval(int semid, int value) {union semun su;su.val = value;if (semctl(semid, 0, SETVAL, su) == -1)err_exit("sem_setval error");return 0; } /** 示例2: 獲取信號量集中第一個信號所關聯的值(GETVAL) 注意: 此時第四個參數可以不填, 而信號量所關聯的值可以通過semctl的返回值返回(the value of semval.) **/ int sem_getval(int semid) {int value = semctl(semid, 0, GETVAL);if (value == -1)err_exit("sem_getval error");return value;return 0; } /** 示例3: 刪除一個信號量集(注意是刪除整個集合)IPC_RMID Immediately remove(立刻刪除) the semaphore set, awakening all processes blocked in semop(2) calls on the set (with an error return and errno set to EIDRM)[然后喚醒所有阻塞在該信號量上的進程]. The argument semnum is ignored[忽略第二個參數]. **/ int sem_delete(int semid) {if (semctl(semid, 0, IPC_RMID) == -1)err_exit("sem_delete error");return 0; }//測試代碼 int main(int argc,char *argv[]) {int semid = sem_create(0x1234); //創建一個信號量集sem_setval(semid, 500); //設置值cout << sem_getval(semid) << endl; //獲取值sleep(10);sem_delete(semid); //刪除該集合 } /**示例4: 獲取/設置信號量的權限 注意:一定要設定struct semid_ds結構體, 以指定使用semun的哪個字段 **/ int sem_getmode(int semid) {union semun su;// 注意: 下面這兩行語句一定要設定.// (告訴內核使用的semun的哪個字段)struct semid_ds sd;su.buf = &sd;//if (semctl(semid, 0, IPC_STAT, su) == -1)err_exit("sem_getmode error");printf("current permissions is: %o\n", su.buf->sem_perm.mode);return 0; } int sem_setmode(int semid, char *mode) {union semun su;// 注意: 下面這兩行語句一定要設定.// (告訴內核使用的semun的哪個字段)struct semid_ds sd;su.buf = &sd;//sscanf(mode, "%o", (unsigned int *)&su.buf->sem_perm.mode);if (semctl(semid, 0, IPC_SET, su) == -1)err_exit("sem_setmode error");return 0; }

semop

int semop(int semid, struct sembuf *sops, unsigned nsops);

? ?用來操縱一個信號量集,?以實現P,V操作

參數:

? ?semid:是該信號量的標識碼,也就是semget函數的返回值

? ?sops:是個指向一個結構數組(如果信號量集中只有一個信號量的話,?只有一個結構體也可)的指針

? ?nsops:所設置的信號量個數(如果nsops>1話,?需要將sops[第二個參數]設置成為一個結構數組,?具體參考Man-Page給出的示例代碼),?第三個參數其實也指出第二個參數所表示對象的個數;

//sembuf結構體 struct sembuf {unsigned short sem_num; /*semaphore number:信號量的編號(從0開始)*/short sem_op; /* semaphore operation(+1, 0, -1) */short sem_flg; /* operation flags: 常用取值為SEM_UNDO(解釋見下) */ };

? ?sem_op是信號量一次PV操作時加減的數值,一般只會用到兩個值,一個是“-1”,也就是P操作,等待信號量變得可用;另一個是“+1”,也就是V操作,發出信號量已經變得可用,?該參數還可以等于0,?表示進程將阻塞直到信號量的值等于0;

? ?sem_flg有三個取值:?SEM_UNDO(在進程結束時,?將該進程對信號量的操作復原[即:取消該進程對信號量所有的操作],?推薦使用),?IPC_NOWAIT(非阻塞)或0(默認操作,?并不撤銷操作);

/** 示例: P,V操作封裝 **可以將sembuf的第三個參數設置為IPC_NOWAIT/0, 以查看程序的狀態的變化 **/ int sem_P(int semid) {struct sembuf sops = {0, -1, SEM_UNDO};if (semop(semid, &sops, 1) == -1)err_exit("sem_P error");return 0; } int sem_V(int semid) {struct sembuf sops = {0, +1, SEM_UNDO};if (semop(semid, &sops, 1) == -1)err_exit("sem_V error");return 0; }
/** 信號量綜合運用示例: 編譯完成之后, 直接運行./semtool, 程序將打印該工具的用法; 下面的這些函數調用, 只不過是對上面所封裝函數的稍稍改動, 理解起來并不困難; **/ //semtool.cpp #include "Usage.h"int main(int argc,char *argv[]) {int opt = getopt(argc, argv, "cdpvs:gfm:");if (opt == '?')exit(EXIT_FAILURE);else if (opt == -1){usage();exit(EXIT_FAILURE);}key_t key = ftok(".", 's');int semid;switch (opt){case 'c':sem_create(key);break;case 'd':semid = sem_open(key);sem_delete(semid);break;case 'p':semid = sem_open(key);sem_P(semid);sem_getval(semid);break;case 'v':semid = sem_open(key);sem_V(semid);sem_getval(semid);break;case 's':semid = sem_open(key);sem_setval(semid, atoi(optarg));sem_getval(semid);break;case 'g':semid = sem_open(key);sem_getval(semid);break;case 'f':semid = sem_open(key);sem_getmode(semid);break;case 'm':semid = sem_open(key);sem_setmode(semid, argv[2]);sem_getmode(semid);break;default:break;}return 0; } //Usage.h #ifndef USAGE_H_INCLUDED #define USAGE_H_INCLUDED#include <iostream> #include <string>#include <stdio.h> #include <stdlib.h> #include <string.h> #include <string.h>#include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/msg.h> #include <sys/shm.h> #include <sys/mman.h> #include <sys/sem.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #include <grp.h> #include <pwd.h> #include <time.h> #include <errno.h> #include <mqueue.h> using namespace std; inline void err_quit(std::string message); inline void err_exit(std::string message);void usage() {cerr << "Usage:" << endl;cerr << "./semtool -c #create" << endl;cerr << "./semtool -d #delte" << endl;cerr << "./semtool -p #signal" << endl;cerr << "./semtool -v #wait" << endl;cerr << "./semtool -s <val> #set-value" << endl;cerr << "./semtool -g #get-value" << endl;cerr << "./semtool -f #print-mode" << endl;cerr << "./semtool -m <mode> #set-mode" << endl; }int sem_create(key_t key) {int semid = semget(key, 1, IPC_CREAT|IPC_EXCL|0666);if (semid == -1)err_exit("sem_create error");return semid; } int sem_open(key_t key) {int semid = semget(key, 0, 0);if (semid == -1)err_exit("sem_open error");return semid; }union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ };int sem_getmode(int semid) {union semun su;// 注意: 下面這兩行語句一定要設定.// (告訴內核使用的semun的哪個字段)struct semid_ds sd;su.buf = &sd;//if (semctl(semid, 0, IPC_STAT, su) == -1)err_exit("sem_getmode error");printf("current permissions is: %o\n", su.buf->sem_perm.mode);return 0; } int sem_setmode(int semid, char *mode) {union semun su;// 注意: 下面這兩行語句一定要設定.// (告訴內核使用的semun的哪個字段)struct semid_ds sd;su.buf = &sd;//sscanf(mode, "%o", (unsigned int *)&su.buf->sem_perm.mode);if (semctl(semid, 0, IPC_SET, su) == -1)err_exit("sem_setmode error");return 0; } int sem_getval(int semid) {int value = semctl(semid, 0, GETVAL);if (value == -1)err_exit("sem_getval error");cout << "current value: " << value << endl;return value; } int sem_setval(int semid, int value) {union semun su;su.val = value;if (semctl(semid, 0, SETVAL, su) == -1)err_exit("sem_setval error");return 0; }int sem_delete(int semid) {if (semctl(semid, 0, IPC_RMID) == -1)err_exit("sem_delete error");return 0; }// 為了能夠打印信號量的持續變化, 因此sem_flg我們并沒用SEM_UNDO // 但是我們推薦使用SEM_UNDO int sem_P(int semid) {struct sembuf sops = {0, -1, 0};if (semop(semid, &sops, 1) == -1)err_exit("sem_P error");return 0; } int sem_V(int semid) {struct sembuf sops = {0, +1, 0};if (semop(semid, &sops, 1) == -1)err_exit("sem_V error");return 0; }inline void err_quit(std::string message) {std::cerr << message << std::endl;exit(EXIT_FAILURE); } inline void err_exit(std::string message) {perror(message.c_str());exit(EXIT_FAILURE); }#endif // USAGE_H_INCLUDED

附-Makefile

.PHONY: clean all CC = g++ CPPFLAGS = -Wall -g BIN = semtool SOURCES = $(BIN.=.cpp) all: $(BIN)%.o: %.c $(CC) $(CPPFLAGS) -c $^ -o $@ main: main.o$(CC) $(CPPFLAGS) $^ -lrt -o $@clean:-rm -rf $(BIN) *.o bin/ obj/ core

總結

以上是生活随笔為你收集整理的Linux IPC实践(11) --System V信号量(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲风情第一页 | 日韩一区二区中文字幕 | 性色免费视频 | 茄子视频色 | 日韩www.| 欧美亚洲免费 | av不卡网| 青青操网| 一区二区三区视频在线免费观看 | 性v天堂| 五月天亚洲综合 | 欧洲熟妇的性久久久久久 | 国产主播毛片 | 成人av18 | 色在线视频观看 | 欧美极品一区二区三区 | 免费成人在线网站 | www.日本免费 | 成人免费超碰 | 国产黑丝91| 99色影院 | 岛国激情 | 亚洲激情网 | 亚洲aaaaaa | 中文字幕一区二区人妻视频 | 97公开视频| 色很久 | 日韩福利在线 | 一色桃子juy758在线播放 | 国产又大又粗又爽的毛片 | 91免费在线 | 国产性爱精品视频 | 久久福利精品 | 香蕉911| 91色噜噜 | 亚洲成人少妇 | 国产污片在线观看 | 色视频在线观看免费 | 亚洲自拍偷拍色图 | 国产大片一区二区三区 | 亚洲爽爽网 | 特大黑人巨人吊xxxx | 国产不卡视频在线播放 | 久久精品噜噜噜成人 | 怡红院av久久久久久久 | 婷婷综合另类小说色区 | 日韩国产精品一区二区 | 国产精品久久久久无码av | 日本中文视频 | 日日拍拍 | 亚洲第一视频在线观看 | 在线观看a网站 | 国产人妖ts重口系列网站观看 | 青青成人 | 91免费视频入口 | 都市豪门艳霸淫美妇 | 老司机午夜免费视频 | 国产黄色大片在线观看 | 人人插人人爽 | 伊人黄网 | www.四虎精品 | 91偷拍一区二区三区精品 | 日本一级黄色大片 | 综合欧美亚洲 | 国产特黄一级片 | 国产精品情侣 | jizzjizz在线观看 | 国产精品xxxx喷水欧美 | 玖玖玖在线观看 | 亚洲不卡免费视频 | 美女黄色片网站 | 成年人看的毛片 | 欧美成人tv| 五月婷婷免费视频 | 鲁一鲁啪一啪 | 成人性生交视频免费观看 | 国产日韩精品一区二区三区 | xxxxx18日本| 精品人妻av在线 | 亚洲熟妇av一区二区三区漫画 | 91蝌蚪视频在线 | 超碰123| 国产中文字幕在线视频 | julia一区二区中文久久97 | 免费视频网站www | 日韩高清不卡 | 狠狠人妻久久久久久综合 | 国产91精品久久久 | 香蕉蜜桃视频 | 国产资源av | 国产乱人伦 | 欧日韩一区二区三区 | 一区二区不卡免费视频 | 亚洲国产精品999 | 禁网站在线观看免费视频 | 波多野久久 | 青青草十七色 | 国产真人做爰视频免费 | 99久久99久久精品国产片果冰 |