1、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。這在一個進程等待完全空閑的資源時使用。
2、急!LINUX下,GCC編譯,原程序包含<semaphore.h>頭文件,為什麼編譯時說sem_wait,sem_post等未定義的引用
編譯時加上參數:-lpthread
要看報錯的階段,是在編譯還是鏈接階段.
如果編譯時函數沒有找到,那是頭文件的問題,如果鏈接時未定義引用,那是c庫的問題.
如果你的頭文件都正常包含了,那可能你的c庫沒有使能semaphore的支持.
3、關於linux下的多線程使用sem信號量的運行問題
不是信號量的問題
printf函數,是先寫到輸出緩沖,遇到\n時,或者緩沖區滿時,或者有強制輸出(fflush)時,才會將緩沖區里的內容輸出到屏幕上(標准輸出設備:stdout)。你的代碼裡面並沒有以上3個觸發條件的任意一種,所以printf的內存沒有實際輸出到屏幕上。
你只要在每個printf函數後面加上fflush(stdout);就可以了。
4、如何使用Linux提供的信號量來實現進程的互斥和同步?
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<semaphore.h>
#include<stdlib.h>
#define N 3
pthread_mutex_t mutex_w,mutex_r; // 定義讀寫互斥鎖
sem_t sem_w,sem_r; //定義讀寫信號量
int data[N];
int pos=0;
void *function_w(void *arg)
{
int w = *(int *)arg;
pos = w;
while(1)
{
usleep(100000);
sem_wait(&sem_w);//等待可寫的資源
pthread_mutex_lock(&mutex_w);//禁止別的線程寫此資源
data[pos] = w;
w++;
w++;
w++;
pos++;
pos=pos%N;
pthread_mutex_unlock(&mutex_w);//別的線程可寫此資源
sem_post(&sem_r);// 釋放一個讀資源
}
return (void *)0;
}
void *function_r(void *arg)
{
while(1)
{
sem_wait(&sem_r);//等待可讀的資源
pthread_mutex_lock(&mutex_r);//禁止別的線程讀此資源
printf("%d\n",data[(pos+N-1)%N]);
pthread_mutex_unlock(&mutex_r);//別的線程可讀此資源
sem_post(&sem_w);// 釋放一個寫資源
}
return (void *)0;
}
int main(int argc, char **argv)
{
pthread_t thread[2*N];
int i;
pthread_mutex_init(&mutex_w,NULL);
pthread_mutex_init(&mutex_r,NULL);
sem_init(&sem_w,0,N);
sem_init(&sem_r,0,0);
for(i=0;i<N;i++)
{
if ( pthread_create(&thread[i],NULL,function_w,(void *)&i) < 0)//創建寫線程
{
perror("pthread_create");
exit(-1);
}
}
for(i=N;i<2*N;i++)
{
if ( pthread_create(&thread[i],NULL,function_r,NULL) < 0)//創建讀線程
{
perror("pthread_create");
exit(-1);
}
}
sleep(1);
return(0);
}
5、linux下怎樣實現WaitForSingleObject的功能
windows的WaitForSingleObject這個介面超級混亂,
等線程用 pthread_join,
等semphore用 sem_wait
等mutex用 pthread_mutex_lock
windows偏要做大而全, 讓人很無奈.
6、linux信號量的問題
sem_init:初始化信號量sem_t,初始化的時候可以指定信號量的初始值,以及是否可以在多進程間共享。
sem_wait:一直阻塞等待直到信號量>0。
sem_timedwait:阻塞等待若干時間直到信號量>0。
sem_post:使信號量加1。
sem_destroy:釋放信號量。和sem_init對應。 答案補充 關於各函數的具體參數請用man查看,如man sem_init可查看該函數的幫助
7、linux C編程
哈哈,又是段錯誤
我也有過同樣的遭遇,我是用國外的一個程序,編譯可以通過,運行就段錯誤。
後來我試了一些版本。發現只有幾個特定版本才行。
我也不知道為什麼。
8、LINUX下多線程編譯問題
你編譯的時候有加多線程連接選項嗎? 要加上 -lpthread 或者 -pthread (盡量選後者)
例如 gcc -pthread -o test main.cpp
另外你的線程創建的不對,函數指針不能強轉類型(這里也不用轉)
pthread_create(&procter_t,NULL,(void*)procter_f,NULL);
pthread_create(&consumer_t,NULL,(void*)consumer_f,NULL);
應該是
pthread_create(&procter_t,NULL,procter_f,NULL);
pthread_create(&consumer_t,NULL,consumer_f,NULL);