查看进程中有多少个线程,查看线程的lwp
ps -lf 进程id(pid)
执行结果:lwp列
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
注意:信号和线程最好不要一起使用。又用信号又用多线程的架构不太合理。
线程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]); } }
如对本文有疑问, 点击进行留言回复!!
clion+vs编译器+Qt5中使用QPrinter和QprintDialog类
基于open62541在QT编写OPCUA特定的客户端程序(含有源码) + VS2015 C语言搭建OPCUA客户端环境
网友评论