在linux中,线程与进程最大的区别就是是否共享同一块地址空间,而且共享同一块地址空间的那一组线程将显现相同的PID号。
在实际编程应用中,我们会很容易发现并证明,一组同源线程的PID都是一样的,但它们的PID真的一样么?
在linux中,线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:
- clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND,0);
对比一下,一个普通的fork()的实现是:
- clone(SIGCHLD,0);
- clone(CLONE_VFORK|CLONE_VM|SIGCHLD,0);
CLONE_FILES 父子进程共享打开的文件
CLONE_FS 父子进程共享文件系统信息
CLONE_SIGHAND 父子进程共享信号处理函数
CLONE_VM 父子进程共享地址空间
CLONE_VFORK 调用vfork(),所以父进程准备睡眠等待子进程将其唤醒
下面用一段程序测试一下,代码如下:
这段测试程序是主线程创建10个线程,并分别打印PID及TID。
- #include<stdio.h>
- #include<stdlib.h>
- #include<pthread.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<string.h>
-
- pthread_ttid[10];
-
- void*thread_handler(void*arg)
- {
- printf("tid%d:%u,pid:%u\n",(int)arg,(unsigned)pthread_self(),
- (unsigned)getpid());
- while(1){
- sleep(1);
- }
- returnNULL;
- }
-
- intmain(void)
- {
- inti,ret;
- pid_tpid;
- printf("main tid:%u,pid:%u\n",(unsigned)pthread_self(),
- (unsigned)getpid());
- for(i=0;i<10;i++){
- if((ret=pthread_create(&tid[i],NULL,thread_handler,
- (void*)i))!=0){
- fprintf(stderr,"pthread_create:%s\n",
- strerror(ret));
- exit(1);
- }
- }
- sleep(3);
- pid=fork();
- if(pid==0){
- printf("son tid:%u,pid:%u\n",(unsigned)pthread_self(),
- (unsigned)getpid());
- while(1);
- sleep(1);
- }
- while(1)
- sleep(2);
- exit(0);
- }
- zx@zhangxu:~/lianxi/apue$gcc-o test pthreadid.c-lpthread
- zx@zhangxu:~/lianxi/apue$./test
- main tid:3077888816,pid:2418
tid0:3077880688,pid:2418
tid1:3069487984,pid:2418
tid2:3061095280,pid:2418
tid3:3052702576,pid:2418
tid4:3044309872,pid:2418
tid5:3035917168,pid:2418
tid6:3027524464,pid:2418
tid7:3019131760,pid:2418
tid8:3010739056,pid:2418
tid9:3002346352,pid:2418
son tid:3077888816,pid:2429
在另一个终端调用pstree -pu
- ├─gnome-terminal(1624,zx)─┬─bash(1628)
│ ├─bash(1704)───pstree(2430)
│ ├─bash(1927)───test(2418)─┬─test(2429)
│ │ ├─{test}(2419)
│ │ ├─{test}(2420)
│ │ ├─{test}(2421)
│ │ ├─{test}(2422)
│ │ ├─{test}(2423)
│ │ ├─{test}(2424)
│ │ ├─{test}(2425)
│ │ ├─{test}(2426)
│ │ ├─{test}(2427)
│ │ └─{test}(2428)
从中可以看出,每个线程的PID其实是不同的,因为测试程序是理想状态,只有一个主线程在创建线程,所以PID的值都是连续的。
参考资料:《linux内核设计与实现》
----