2015-11-10 138 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;