我正在研究以下function。 这个函数应该创buildn个线程。 它也应该打印子线程的tid。 但目前我有点困惑。 当我执行它,例如我创build5个线程,它始终返回相同的tid。 据我了解,tid是调用者的线程ID。 同一个调用者调用所有这些线程还是我有什么问题。 代码如下:
void spawnThreads( unsigned int n) { int threads = n, ret = -1; pthread_t * thread = malloc(sizeof(pthread_t)*threads); pid_t tid; int i; for(i = 0; i < threads; i++) { ret = pthread_creation(&thread[i], NULL, (void *(*)(void *)) foo, NULL); // foo does not do anything if( ret != 0) { printf("pthread error!\n"); } tid = syscall(SYS_gettid); printf("%d %d\n", i, tid); printf("I just created thread %d\n", i); pthread_join(thread[i],NULL); } void * foo(void) { return NULL; }
例如,我得到了以下inputspawnThreads(4)的以下输出:
0 2411 I just created thread 0 1 2411 I just created thread 1 2 2411 I just created thread 2 3 2411 I just created thread 3
总之,函数应该打印> i <> tid < 。 > tid <表示孩子的TID, > i <从1到n。
但是,为什么我得到同样的tid四倍? 我做错了什么? 我将不胜感激,如果有人能解释我出了什么问题。
每个线程获得相同TID的原因是每次从主线程调用syscall(SYS_gettid)
,而不是从创建的新线程中syscall(SYS_gettid)
。 你需要从你的线程函数内部调用它,然后提供一个方法将信息传递回主线程,如果需要的话。
作为一种实现方法的示例(省略了一些错误检查):
创建一个结构来保存互斥锁,条件,TID和一个标志,以指示TID何时有效。
struct s_threadId { pthread_mutex_t mtx; /* mutex & condition to allow main thread to wait for the new thread to set its TID */ pthread_cond_t cond; /* '' */ pid_t id; /* to hold new thread's TID */ int ready; /* to indicate when 'id' is valid, in case the condition wait gets interrupted */ };
然后改变你的线程函数来锁定,设置和发信号(并且在 spawnThreads()
之前移动它,使得它的声明是可见的):
void *foo(void *arg) { struct s_threadId *thId = arg; /* Lock mutex... */ pthread_mutex_lock(&thId->mtx); /* Get and save TID and ready flag.. */ thId->id = syscall(SYS_gettid); thId->ready = 1; /* ..and signal main thread that we're ready */ pthread_cond_signal(&thId->cond); /* ..then unlock when we're done. */ pthread_mutex_unlock(&thId->mtx); /* ... */ return NULL; }
…并修改您的spawnThreads
函数来初始化/清理结构成员,并得到TID一旦线程设置它:
void spawnThreads(unsigned int n) { pthread_t thread; /* reused for each thread, since they run 1 at a time */ /* struct to pass back TID */ struct s_threadId threadId; pthread_cond_init(&threadId.cond, NULL); /* init condition */ pthread_mutex_init(&threadId.mtx, NULL); /* init mutex */ int i; for (i = 0; i < n; i++) { /* lock mutex *before* creating the thread, to make the new thread wait until we're ready before signaling us */ pthread_mutex_lock(&threadId.mtx); /* clear ready flag before creating each thread */ threadId.ready = 0; /* create threads and pass address of struct as argument */ if (pthread_create(&thread, NULL, foo, &threadId)) { printf("pthread error!\n"); } else { /* Wait on the condition until the ready flag is set */ while (!threadId.ready) { pthread_cond_wait(&threadId.cond, &threadId.mtx); } /* Now we have the TID... */ printf("%d %d\n", i, threadId.id); printf("I just created thread %d\n", i); } /* ..and unlock the mutex when done. */ pthread_mutex_unlock(&threadId.mtx); pthread_join(thread, NULL); } /* When we're completely done with the struct we need to clean up the mutex and condition variable */ pthread_mutex_destroy(&threadId.mtx); pthread_cond_destroy(&threadId.cond); }
在上面,需要互斥和条件等待,以确保主线程不会尝试打印TID,直到新线程有机会设置它。 主线程启动新线程,然后等待,并在完成存储TID的时候发出新的线程信号,主线程可以继续。
人们通常感兴趣的信息有三种:进程ID,线程ID和pthreads线程ID。 所有的pthread
调用都是独立的,他们使用自己的线程id。 由于pthreads API之外的原因,进程ID和OS线程ID可能很重要。
Pthread ID由pthread_create
和pthread_self
报告,前者报告它创建的线程,后者报告它本身。 否则,这是鸡和鸡蛋的情况。 一个线程不能问另一个线程它的id是什么,除非它已经知道它的id是什么。 如果这很重要的话,一些机制,一个全局列表,一些IPC等等,都必须建立起来才能完成。
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <pthread.h> #include <sys/syscall.h> #include <string.h> typedef struct { int i; pid_t pid; // linux pid pid_t tid; // linux thread id pthread_t ptid; // pthreads tid } data; void *foo(void *args) { data *p = (data *) args; p->pid = getpid(); p->tid = syscall(SYS_gettid); p->ptid = pthread_self(); return(p); } void spawnThreads(unsigned int numThreads) { int ret; pthread_t *tids = malloc(sizeof(pthread_t) * numThreads); int i; for (i = 0; i < numThreads; i++) { data *dp = malloc(sizeof(data) * numThreads); memset(dp, '\0', sizeof(*dp)); dp->i = i; ret = pthread_create(&tids[i], NULL, foo, (void *) dp); if ( ret != 0) perror("pthread create error"); } for (int i = 0; i < numThreads; ++i) { data *status; ret = pthread_join(tids[i], (void *) &status); if ( ret != 0) perror("pthread join error"); else { printf("thread num %d joined and reports pthreadId of %lu " "process pid of %d and linux tid of %d\n", status->i, status->ptid, status->pid, status->tid); free(status); } } free(tids); } int main(int argc, char *argv[]) { printf("main thread reports pthreadId of............ %lu " "process pid of %d and linux tid of %ld\n", pthread_self(), getpid(), syscall(SYS_gettid)); spawnThreads(5); return (0); }