信號量比互斥鎖高級,互斥鎖只容許一個線程訪問臨界區,信號量能夠多個,能夠把信號量看做成互斥鎖的升級版,可是若是能用互斥鎖解決,就用互斥鎖,互斥鎖比信號量節省資源。html
1,建立有名字的信號量,建立成功後,會在ubuntu的/dev/shm目錄下,生成一個文件,名字爲【sem.name】。【sem】是固定的,【name】是函數sem_open的第一個參數。c++
名字的信號量的生命週期和內核同樣,只要系統不重啓,它就一直存在。shell
#include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
2,刪除有名字的信號量,並刪除文件。ubuntu
#include <semaphore.h> int sem_unlink(const char *name);
返回值:成功0微信
失敗:-1,設置errno函數
EACCES:沒有權限訪問這個信號量對應的文件 ENAMETOOLONG:信號量的名字長了 ENOENT:信號量不存在
3,取得信號量的value值post
#include <semaphore.h> int sem_getvalue(sem_t *sem, int *sval);
4,若是信號量的value值大於0,把信號量的value值-1;若是信號量的value值小於1,阻塞等待,直到信號量的value值大於0。注意:在ubuntu下,若是sem_wait執行前,value值爲0,sem_wait執行後,value也不會變成-1,再次執行sem_wait,value仍是0。可是有的unix系統value會變成負數。即便value不變成負數,內核也會準確記錄它的值。學習
#include <semaphore.h> int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
sem:信號量指針線程
返回值:成功0;失敗:unix
sem_trywait():不阻塞等待。
sem_timedwait():
5,把信號量的value值+1。
#include <semaphore.h> int sem_post(sem_t *sem);
semcreate.c
#include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char** argv){ int c, flags; unsigned int val = 1; sem_t* sem; flags = O_RDWR | O_CREAT; while((c = getopt(argc, argv, "ei:")) != -1){ switch(c){ case 'e': flags |= O_EXCL; break; case 'i': val = atoi(optarg); break; } } if(optind != argc - 1){ printf("usage error\n"); return -1; } sem = sem_open(argv[optind], flags, 0664, val); if(sem == SEM_FAILED){ perror("sem"); return -1; } sem_close(sem); exit(0); }
semunlink.c
#include <semaphore.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char** argv){ if(argc != 2){ printf("usage err\n"); exit(1); } if(sem_unlink(argv[1]) == -1){ perror("sem_unlink"); } }
semgetvalue.c
#include <semaphore.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char** argv){ sem_t* sem; int val; if(argc != 2){ printf("usage error\n"); exit(1); } sem = sem_open(argv[1], 0); sem_getvalue(sem, &val); printf("value = %d\n", val); exit(0); }
semwait.c
#include <semaphore.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char** argv){ sem_t* sem; int val; if(argc != 2){ printf("usage error\n"); exit(1); } sem = sem_open(argv[1], 0); sem_wait(sem); sem_getvalue(sem, &val); printf("pid %ld has semaphore, value = %d\n", (long) getpid(), val); pause(); exit(0); }
sempost.c
#include <semaphore.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char** argv){ sem_t* sem; int val; if(argc != 2){ printf("usage error\n"); exit(1); } sem = sem_open(argv[1], 0); sem_post(sem); sem_getvalue(sem, &val); printf("value = %d\n", val); exit(0); }
ubuntu$ ./semcreate test1 ubuntu$ ls -l /dev/shm/ total 4 -rw-r--r-- 1 ys ys 32 6月 21 16:25 sem.test1
ubuntu$ ./semgetvalue test1 value = 1
ubuntu$ ./semwait test1 pid 2995 has semaphore, value = 0 ^C ubuntu$
ubuntu$ ./semgetvalue test1 value = 0
ubuntu$ ./semwait test1 & [8] 3000 ubuntu$ ./semgetvalue test1 value = 0 ubuntu$ ./semwait test1 & [9] 3002 ubuntu$ ./semgetvalue test1 value = 0
ubuntu$ ./sempost test1 pid 3000 has semaphore, value = 0 //來之第一個sem_wait程序的輸出 value = 0
ubuntu$ ./sempost test1 pid 3002 has semaphore, value = 0 //來之第二個sem_wait程序的輸出 value = 0
ubuntu$ ./sempost test1 value = 1
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #define NBUFF 10 #define SEM_MUTEX "mutex" #define SEM_NEMPTY "nempty" #define SEM_NSTORED "nstored" int nitems; struct { int buff[NBUFF]; sem_t *mutex, *nempty, *nstored; } shared; void* produce(void *args){ int i; for(i = 0; i < nitems; ++i){ sem_wait(shared.nempty); sem_wait(shared.mutex); shared.buff[i % NBUFF] = i; sem_post(shared.mutex); sem_post(shared.nstored); } return NULL; } void* consume(void* args){ int i; for(i = 0; i < nitems; ++i){ sem_wait(shared.nstored); sem_wait(shared.mutex); shared.buff[i % NBUFF] = i; sem_post(shared.mutex); sem_post(shared.nempty); } return NULL; } int main(int argc, char** argv){ pthread_t tid_produce, tid_consume; if(argc != 2){ printf("usage error\n"); exit(1); } nitems = atoi(argv[1]); //create 3 semaphore shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL, 0664, 1); shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL, 0664, NBUFF); shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL, 0664, 0); //create produce and consume thread pthread_create(&tid_produce, NULL, produce, NULL); pthread_create(&tid_consume, NULL, consume, NULL); //wait for 2 thread pthread_join(tid_produce, NULL); pthread_join(tid_consume, NULL); sem_unlink(SEM_MUTEX); sem_unlink(SEM_NEMPTY); sem_unlink(SEM_NSTORED); exit(0); }