linux线程的线程ID与其进程ID
2012-03-02 12:31
197 查看
在linux中,线程与进程最大的区别就是是否共享同一块地址空间,而且共享同一块地址空间的那一组线程将显现相同的PID号。
在实际编程应用中,我们会很容易发现并证明,一组同源线程的PID都是一样的,但它们的PID真的一样么?
在linux中,线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);
上面的代码产生的结果和调用fork()差不多,只是父子俩共享地址空间、文件系统资源、文件描述符和信号处理程序。换个说法就是,新建的进程和它的父进程就是流行的所谓线程。
对比一下,一个普通的fork()的实现是:
clone(SIGCHLD, 0);
而vfork()的实现是:
clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0);
传递给clone()的参数标志决定了新创建进程的行为方式和父子进程之间共享的资源种类。下面列举部分clone()参数标志,这些是在<linux/sched.h>中定义的。
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_t tid[10];
void * thread_handler(void *arg)
{
printf("tid%d:%u,pid:%u\n", (int)arg, (unsigned)pthread_self(),
(unsigned)getpid());
while(1){
sleep(1);
}
return NULL;
}
int main(void)
{
int i, ret;
pid_t pid;
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
从结果可以看出,测试程序中所有线程的PID都相同。
在另一个终端调用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内核设计与实现》
----
转自:linux线程的线程ID与其进程ID
在实际编程应用中,我们会很容易发现并证明,一组同源线程的PID都是一样的,但它们的PID真的一样么?
在linux中,线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);
上面的代码产生的结果和调用fork()差不多,只是父子俩共享地址空间、文件系统资源、文件描述符和信号处理程序。换个说法就是,新建的进程和它的父进程就是流行的所谓线程。
对比一下,一个普通的fork()的实现是:
clone(SIGCHLD, 0);
而vfork()的实现是:
clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0);
传递给clone()的参数标志决定了新创建进程的行为方式和父子进程之间共享的资源种类。下面列举部分clone()参数标志,这些是在<linux/sched.h>中定义的。
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_t tid[10];
void * thread_handler(void *arg)
{
printf("tid%d:%u,pid:%u\n", (int)arg, (unsigned)pthread_self(),
(unsigned)getpid());
while(1){
sleep(1);
}
return NULL;
}
int main(void)
{
int i, ret;
pid_t pid;
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
从结果可以看出,测试程序中所有线程的PID都相同。
在另一个终端调用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内核设计与实现》
----
转自:linux线程的线程ID与其进程ID
相关文章推荐
- linux线程的线程ID与其进程ID
- linux查看某个进程的线程id(spid)
- linux 线程ID与进程ID 初探
- Linux线程ID和进程ID
- C/C++ 获取Linux线程ID与进程ID
- linux 线程id 与进程id对应关系
- linux下多线程学习4_打印线程id和进程id
- 03.linux进程与线程
- 3.3 进程管理_线程在Linux中的实现
- Linux下编程为什么多用进程少用线程
- C# 获得当前 进程 或 线程的ID
- linux 获取线程ID的方法
- Linux 进程与线程一(创建-关闭线程)
- 打通Linux脉络系列:进程、线程和调度
- linux如何根据进程ID查找启动程序的路径
- Windows/Linux环境下查看Java进程ID方法
- 如何在Windows和Linux下获取当前线程的ID号
- linux下查看TCP端口所属进程/线程
- Linux下获取线程ID的方法
- linux查看进程所有子进程和线程