查看進程中有多少個線程,查看線程的LWPlinux
ps -Lf 進程ID(pid)
執行結果:LWP列shell
y:~$ ps -Lf 1887 UID PID PPID LWP C NLWP STIME TTY STAT TIME CMD ys 1887 1341 1887 0 3 14:57 tty2 Sl 0:00 /usr/lib/ibus/ibus ys 1887 1341 1889 0 3 14:57 tty2 Sl 0:00 /usr/lib/ibus/ibus ys 1887 1341 1890 0 3 14:57 tty2 Sl 0:00 /usr/lib/ibus/ibus
注意:信號和線程最好不要一塊兒使用。又用信號又用多線程的架構不太合理。session
線程ID多線程
處理器現場和棧指針(內核棧)架構
獨立的棧空間(用戶空間棧)併發
errno變量函數
因此不能用函數perrno打印錯誤信息了。性能
使用strerror函數打印錯誤信息線程
#include <string.h> char *strerror(int errnum);
阻塞信號集合指針
調度優先級
每一個線程有本身獨立的PCB
進程id:系統中每一個進程有惟一的id,在c語言中用pid_t類型表示,是個非負整數。
進程狀態:就緒,運行,掛起,中止等狀態
描述虛擬地址空間的信息
描述控制終端的信息
進程執行時的當前工做目錄(current working directory)
umask掩碼
文件描述符表,包含不少指向file結構體的指針
和信號相關的信息
用戶id和組id
會話(session)和進程組
進程可使用的資源上限(Resource Limit)
用【ulimit -a】查看:
ys@ys:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7743 max locked memory (kbytes, -l) 16384 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7743 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
編譯的時候要加【-lpthread】
#include <pthread.h> pthread_t pthread_self(void);
例子:獲得主線程的ID和子線程的ID。注意要sleep1秒,不睡的話,主線程就先結束了,因此子線程裏的打印打不出來。
#include <pthread.h> #include <unistd.h> #include <stdio.h> void * thr(void* args){ printf("in thread %d, %lu\n", getpid(), pthread_self()); } int main(){ pthread_t tid; pthread_create(&tid, NULL, thr, NULL); printf("in main thread %d, %lu\n", getpid(), pthread_self()); sleep(1); return 0; }
#include <pthread.h> void pthread_exit(void *retval);
改進上面的例子,用pthread_exit代替sleep
#include <pthread.h> #include <unistd.h> #include <stdio.h> void * thr(void* args){ printf("in thread %d, %lu\n", getpid(), pthread_self()); //exit(1);//不要在子線程裏調用此函數,調用的結果是把整個進程終止了。 //return NULL;//可使用 //pthread_exit(NULL);//可使用 } int main(){ pthread_t tid; pthread_create(&tid, NULL, thr, NULL); printf("in main thread %d, %lu\n", getpid(), pthread_self()); //sleep(1); pthread_exit(NULL); return 0; }
線程不回收也會變成殭屍線程,線程裏也有PCB資源,也要回收。
#include <pthread.h> int pthread_join(pthread_t thread, void **retval);
例子:實驗pthread_join是不是阻塞。
#include <pthread.h> #include <unistd.h> #include <stdio.h> void * thr(void* args){ printf("in thread %d, %lu\n", getpid(), pthread_self()); sleep(1); return (void*)200; } int main(){ pthread_t tid; pthread_create(&tid, NULL, thr, NULL); printf("in main thread %d, %lu\n", getpid(), pthread_self()); void *ret; pthread_join(tid, &ret); printf("return value:%d\n", (int)ret); return 0; }
結果分析,發如今子線程睡的1秒內,pthread_join是阻塞的,線程的返回值200,也能夠打印出來,可是編譯有警告。
用pthread_exit函數也能夠設置線程的返回值和return的效果如出一轍。
pthread_exit((void*)11); return (void*)11;
#include <pthread.h> int pthread_cancel(pthread_t thread);
例子:驗證被函數pthread_cancel終止的進程的返回值。
#include <pthread.h> #include <unistd.h> #include <stdio.h> void * thr(void* args){ while(1){ printf("in thread %d, %lu\n", getpid(), pthread_self()); sleep(1); } pthread_exit((void*)101); //return (void*)200; } int main(){ pthread_t tid; pthread_create(&tid, NULL, thr, NULL); sleep(5); pthread_cancel(tid); void *ret; pthread_join(tid, &ret); printf("return value:%d\n", (int)ret); return 0; }
注意:pthread_cancel可以執行成功的前提是要終止的線程裏必須有Cancellation points。也就是說線程裏不能光是一個空的死循環,循環裏至少要有一行代碼,不然pthread_cancel不能執行成功。
#include <pthread.h> int pthread_detach(pthread_t thread);
例子:驗證分離後,不能夠調用pthread_join函數。
#include <pthread.h> #include <unistd.h> #include <stdio.h> #include <string.h> void * thr(void* args){ while(1){ printf("in thread %d, %lu\n", getpid(), pthread_self()); sleep(1); } pthread_exit((void*)101); //return (void*)200; } int main(){ pthread_t tid; pthread_create(&tid, NULL, thr, NULL); sleep(5); pthread_detach(tid); int ret = pthread_join(tid, NULL); if(ret != 0){ printf("return value:%d, %s\n", ret, strerror(ret)); } return 0; }
結果分析:打印出下面的,errno是22.
return value:22, Invalid argument
getconf GNU_LIBPTHREAD_VERSION NPTL 2.27
CPU核數*2 + 2
#include <pthread.h> int pthread_equal(pthread_t t1, pthread_t t2);
雖然線程ID的類型是pthread_t,也就是無符號長整形,可是也不推薦用==去判斷,由於Linux後續的版本有可能把pthread_t類型變爲構造。
注意:在同一個進程內,線程ID是惟一的。可是在不一樣的進程裏,能夠參數相同的線程ID。這點和進程的ID不一樣,進程ID確定是惟一的。
設置線程屬性的步驟:
1,調用pthread_attr_init函數
#include <pthread.h> int pthread_attr_init(pthread_attr_t *attr);
2,設置屬性。設置屬性的函數以下:
pthread_attr_getaffinity_np pthread_attr_setaffinity_np pthread_attr_getdetachstate pthread_attr_setdetachstate pthread_attr_getguardsize pthread_attr_setguardsize pthread_attr_getinheritsched pthread_attr_setinheritsched pthread_attr_getschedparam pthread_attr_setschedparam pthread_attr_getschedpolicy pthread_attr_setschedpolicy pthread_attr_getscope pthread_attr_setscope pthread_attr_getstack pthread_attr_setstack pthread_attr_getstackaddr pthread_attr_setstackaddr pthread_attr_getstacksize pthread_attr_setstacksize
3,調用pthread_attr_destroy函數
#include <pthread.h> int pthread_attr_destroy(pthread_attr_t *attr);
舉例:先指定線程的屬性是detatch,而後再建立線程。建立線程後就不用再調用pthread_detach函數了。這麼作的好處是,若是線程的執行時間特別短,還沒調用pthread_detach函數,線程就結束了的狀況,程序也能夠正常回收線程的資源。
#include <stdio.h> #include <pthread.h> #include <string.h> void * thr(void* arg){ printf("thread\n"); } int main(){ pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t tid; pthread_create(&tid, &attr, thr, NULL); int ret = pthread_join(tid, NULL); if(ret > 0){ printf("ret:%d, %s\n", ret, strerror(ret)); } pthread_attr_destroy(&attr); }
用malloc開闢內存空間,記得釋放。
#include <stdio.h> #include <pthread.h> #include <string.h> #include <stdlib.h> #include <unistd.h> void * thr(void* arg){ int* pi = arg; printf("%d thread\n", *pi); *pi = 100 + *pi; return pi; } int main(){ pthread_t tid[5]; int* pi[5]; for(int j = 0; j < 5; ++j){ pi[j] = (int*)malloc(sizeof(int)); } int i = 0; for(; i < 5; ++i){ *pi[i] = i; pthread_create(&tid[i], NULL, thr, pi[i]); } void* ret; for(i = 0; i < 5; ++i){ pthread_join(tid[i], &ret); printf("ret:%d\n", *(int*)ret); } for(int i = 0; i < 5; ++i){ free(pi[i]); } }