目录
线程
线程概念:
进程:有独立的进程地址空间,有独立的PCB,是分配资源的最小单位。
线程:有独立的PCB,没有独立的进程地址空间,是最小的执行单位。
LWP是CPU执行的最小单位。
ps -Lf 进程ID
ps -Lf 2813
三级映射
线程共享资源
文件描述符表。
每种信号的处理方式。
当前工作目录。
用户ID和组ID。
内存地址空间。(.text/.data/.bss/heap/.共享库)
共享全局变量。
线程非共享资源
线程ID。
处理器现场和栈指针(内核栈)。
独立的栈空间(用户栈空间)。
errno变量。
信号屏蔽字。
调度优先级。
线程优缺点
优点
提高程序并发性。
开销小。
数据通信、共享数据方便。
缺点
库函数不稳定。
调式、编写困难,gdb不支持。
对信号支持不友好。
pthread_self
获取线程ID。其作用对应进程中getpid()函数。线程ID是进程内部,识别标志。两个进程间,线程 ID 允许相同。
线程ID:pthread_t 类型。
本质:在Linux下为无符号整数(%lu),其他系统中可能是结构体实现。
man 3 pthread_self
返回值
成功:0
失败:无
pthread_create
创建一个新线程。
man 3 pthread_create
参数thread
传出参数,新创建的子线程ID。
参数attr
线程属性。
NULL:表示使用默认属性。
参数3
子线程回调函数。创建成功后,pthread_create函数返回时,该函数会自动执行。
参数4
子线程回调函数的参数。没有参数时,传NULL。
返回值
成功:0
失败:错误号
测试代码1
创建一个线程,并输出内容。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
void *HuiDiao_HanShu()
{
printf("这是子线程的回调函数,子线程的进程ID是%d,子线程ID是%lu。\n", getpid(), pthread_self());
}
int main(int argc, char *argv[])
{
int flag;
pthread_t ZiXianCheng_ID; //子线程ID
flag = pthread_create(&ZiXianCheng_ID, NULL, HuiDiao_HanShu, NULL); //创建子线程
if (flag != 0)
{
perror("创建子线程错误");
exit(1);
}
printf("这是主线程,进程ID是%d,线程ID是%lu。\n", getpid(), pthread_self());
sleep(1);
return 0;
}
测试结果
测试代码2
创建多个子线程。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
void *HuiDiao_HanShu(void *arg)
{
int num;
num = (int )arg+1;
sleep(num);
printf("这是第%d个子线程的回调函数,子线程的进程ID是%d,子线程ID是%lu。\n", num, getpid(), pthread_self());
}
int main(int argc, char *argv[])
{
int flag, i;
pthread_t ZiXianCheng_ID; //子线程ID
for (i = 0; i < 5; i++)
{
flag = pthread_create(&ZiXianCheng_ID, NULL, HuiDiao_HanShu, (void *)i); //创建子线程,传参采用值传递
if (flag != 0)
{
perror("创建子线程错误");
exit(1);
}
}
printf("这是主线程,进程ID是%d,线程ID是%lu。\n", getpid(), pthread_self());
sleep(i+1);
return 0;
}