2015-11-10 188 views
5
#include <stdio.h> 
#include <sys/types.h> 
#include <iostream> 
#include <unistd.h> 
#include <fstream> 
#include <string> 
#include <semaphore.h> 

using namespace std; 

int main(int argc, char *argv[]){ 
    int pshared = 1; 
    unsigned int value = 0; 
    sem_t sem_name; 
    sem_init(&sem_name, pshared, value); 

    int parentpid = getpid(); 
    pid_t pid = fork(); 

    if (parentpid == getpid()){ 
    cout << "parent id= " << getpid() << endl; 
    sem_wait(&sem_name); 
    cout << "child is done." << endl; 
    } 

    if (parentpid != getpid()){ 
    cout << "child id= " << getpid() << endl; 
    for (int i = 0; i < 10; i++) 
     cout << i << endl; 

    sem_post(&sem_name); 
} 
    sleep(4); 
    return 0; 
} 

的結果應該是:信號量爲什麼不起作用?

parent id 123456. 
child id 123457. 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
child is done. 

程序退出,而是它從來沒有信號的信號。

+0

歡迎摘自至U&L!我們有你的代碼和結果應該是什麼......實際結果是什麼?你怎麼確定信號量從未被髮信號?你能編輯你的問題來添加它嗎?到目前爲止,我的代碼中似乎沒有發現任何錯誤 –

回答

7

sem_init的手冊頁:

如果的pshared是非零,那麼信號量在 進程之間共享,並應位於共享內存的 區域(請參閱shm_open(3),mmap(2)和shmget(2))。 (由於由fork(2) 創建的子項繼承其父級的內存映射,因此它也可以訪問信號量。)任何可以訪問共享內存區域的進程都可以使用sem_post(3),sem_wait(3)等等。

POSIX信號量是堆棧結構。它們不是引用計數引用的內核維護結構,如filedescriptors。如果你想共享一個POSIX信號量和兩個進程,你需要自己照顧共享部分。

這應該工作:

#include <fstream> 
#include <iostream> 
#include <semaphore.h> 
#include <stdio.h> 
#include <string> 
#include <sysexits.h> 
#include <sys/mman.h> 
#include <sys/types.h> 
#include <unistd.h> 


int main(int argc, char *argv[]){ 
    using namespace std; 
    sem_t* semp = (sem_t*)mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, 0, 0); 
    if ((void*)semp == MAP_FAILED) { perror("mmap"); exit(EX_OSERR); } 

    sem_init(semp, 1 /*shared*/, 0 /*value*/); 

    pid_t pid = fork(); 
    if(pid < 0) { perror("fork"); exit(EX_OSERR); } 

    if (pid==0){ //parent 
    cout << "parent id= " << getpid() << endl; 
    sem_wait(semp); 
    cout << "child is done." << endl; 
    }else { //child 
    cout << "child id= " << getpid() << endl; 
    for (int i = 0; i < 10; i++) 
     cout << i << endl; 
    sem_post(semp); 
    } 
    return 0; 
} 

注:如果你只想要這種行爲,那麼waitpid顯然是要走的路。我假設你想要測試POSIX信號量。

+0

分叉的孩子是否需要與父級共享內存區域才能訪問信號量?它是否足夠在共享代碼中聲明信號量爲全局變量?當我讀到括號時,我發現括號內的句子令人困惑。 –

+0

@dave_alcarin是+ no。我已經添加了一些示例代碼。 – PSkocik

+0

因此,確實需要一個共享內存,但我認爲手冊頁說的是映射(來自mmap)被繼承。很好的例子! +1 –

4

XY Problem?

如果你想要做的是等待做你的孩子的過程,你不需要信號量,但waitwaitpid。以下C代碼具有您的預期輸出。

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 

int main(void){ 
    pid_t pid; 
    pid = fork(); 
    if (pid < 0) { 
     fprintf(stderr, "fork failed!\n"); 
     return 1; 
    } 
    if (pid == 0) { 
     int i; 
     printf("child id= %d\n", getpid()); 
     for (i = 0; i < 10; i++) { 
      printf("%d\n",i); 
     } 
    } 
    else { 
     int status; 
     printf("parent id= %d\n", getpid()); 
     waitpid(-1, &status, 0); 
     printf("child is done\n"); 
    } 
    return 0; 
} 

注:我用C做,因爲只有C++您正在使用是一個for循環初始聲明,打印出來的cout << "blah" << endl;