2015-07-11 51 views
0

我试图运行下面的代码。在这个question的帮助下,我能够理解应该创建多少个进程和线程,但是,为了让这个更进一步,我尝试让线程执行一个函数。执行线程 - 输出原因

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 

void *runner(void *param) { 
    int i = atoi(param);  
    printf("My thread id is %ld\n",pthread_self()); 
    printf("\nValue of parameter = %d", i); 
    pthread_exit(0); 
} 

int main() 
{ 
    int i = 5; 
    pid_t pid; 
    pthread_t tid; 
    pthread_attr_t attr; 

    pid = fork(); wait(NULL); 

    if (pid == 0) { /* Child Process */ 

     fork(); wait(NULL); 
     pthread_attr_init(&attr); 
     i++; 
     pthread_create(&tid, &attr, runner, &i); 
     pthread_join(tid, NULL); 
    } 
    fork(); wait(NULL); 
    printf("\n\n"); 
    return 0; 
} 

这种情况的输出是: 我的线程id是139919964464896

Value参数= 0

Value参数= 0

我的线程id是139919964464896

参数值= 0

Value参数= 0

这里,我无法弄清楚:

  1. 为什么行我的线程ID为139919964464896得到,而线值参数= 0获取打印打印两次四次。
  2. 为什么当传递的参数初始化为5并增加到6时,该值会打印为0?

请问,有人可以帮助我吗?提前致谢!

回答

2

为什么行我的线程ID是139919964464896获取打印两次 而参数= 0的行被打印四次。

当你fork(),每个进程也从父节点(所有其他的东西)获得缓冲区的副本。通常stdout(标准输出)是线路缓冲的。这意味着当您打印换行符(\n)或明确清空缓冲区时,缓冲区将被刷新,即调用fflush(stdout); 当您第一次调用fork()时,缓冲区中没有任何内容(即,目前为止尚未打印任何内容)。所以它没有区别。但是当第二次调用fork()时,整个未刷新的缓冲区被复制到子进程。当它退出进程时,两个进程都会刷新其缓冲区。因此Value of parameter = 0被打印两次。

但是行My thread id is ....而不是打印两次,因为\n强制缓冲区被刷新。

因此,无论在末尾添加一个新行:

printf("\nValue of parameter = %d\n", i); 
           ^forces flushing the output buffer 

或调用fork()第二次之前调用fflush(stdout);

很明显,在第一个fork之后,你有两个进程,它们都会创建一个线程。所以你会看到两个线程的输出。

+0

我刚开始阅读操作系统,这是很多有用的信息。非常感谢解释! :) – Neha

+0

不客气! –

2

你的错误是你怎么会在这里解释线程参数:

int i = atoi(param); 

特性参数的值是“&我”,从“主()”函数,所以参数是一个真正的int*对象已被转换为void*指针。然而,用“atoi”,你把它当作一个字符串来对待。

替换符合:

int* typed_param = (int*) param; 
int i = *typed_param; 

然后事情应该是有意义的。

+0

感谢您的纠正。请你也可以帮助我的第一点,为什么id的线程打印两次和参数值4次? – Neha