资源预览内容
第1页 / 共32页
第2页 / 共32页
第3页 / 共32页
第4页 / 共32页
第5页 / 共32页
第6页 / 共32页
第7页 / 共32页
第8页 / 共32页
第9页 / 共32页
第10页 / 共32页
亲,该文档总共32页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Linux 线程,www.embedu.org,线程基础,每个用户进程有自己的地址空间 系统为每个用户进程创建一个 task_struct来描述该进程 该结构体中包含了一个指针指向该进 程的虚拟地址空间映射表 实际上task_struct 和地址空间映射表一起用来 表示一个进程,task_struct,Memory_map,www.embedu.org,线程基础,由于进程的地址空间是私有的,因此在进程间上下文切换时,系统开销比较大 为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程 在同一个进程中创建的线程共享该进程的地址空间 Linux里同样用task_struct来描述一个线程。线程和进程都参与统一的调度,www.embedu.org,线程基础,通常线程指的是共享相同地址 空间的多个任务 使用多线程的好处 大大提高了任务切换的效率 避免了额外的TLB & cache的刷新,task_struct,task_struct,task_struct,task_struct,task_struct,Memory_map,www.embedu.org,线程基础,多线程通过第三方的线程库来实现 New POSIX Thread Library (NPTL) 是早期Linux Threads的改进 采用1:1的线程模型 显著的提高了运行效率 信号处理效率更高,www.embedu.org,线程基础,一个进程中的多个线程共享以下资源 可执行的指令 静态数据 进程中打开的文件描述符 信号处理函数 当前工作目录 用户ID 用户组ID,www.embedu.org,线程基础,每个线程私有的资源如下 线程ID (TID) PC(程序计数器)和相关寄存器 堆栈 局部变量 返回地址 错误号 (errno) 信号掩码和优先级 执行状态和属性,www.embedu.org,多线程编程,NPTL线程库中提供了如下基本操作 创建线程 删除线程 控制线程 线程间同步和互斥机制 信号量 互斥锁 条件变量,www.embedu.org,多线程编程,www.embedu.org,多线程编程,www.embedu.org,多线程编程,www.embedu.org,多线程示例(1 of 3),#include #include #include #include char message32 = “Hello World”; void *thread_function(void *arg); int main(int argc, char *argv) pthread_t a_thread; void *thread_result; if (pthread_create(&a_thread, NULL, thread_function, (void *)message) 0) /*使用缺省属性创建线程*/,www.embedu.org,多线程示例(2 of 3), perror(“fail to pthread_create”); exit(-1); printf(“waiting for thread to finishn”); if (pthread_join(a_thread, ,www.embedu.org,多线程示例(3 of 3),void *thread_function(void *arg) printf(“thread_function is running, argument is %sn”, (char *)arg); strcpy(message, “marked by thread”); pthread_exit(“Thank you for the cpu time”); 编译多线程程序 # gcc -o sample sample.c -lpthread -D_REENTRANT -lpthread : 链接pthread库 -D_REENTRANT : 生成可重入代码,Linux 线程同步和互斥,www.embedu.org,线程间机制,多线程共享同一个进程的地址空间 优点:线程间很容易进行通信 通过全局变量实现数据共享和交换 缺点:多个线程同时访问共享对象 时需要引入同步和互斥机制,task_struct,task_struct,task_struct,task_struct,task_struct,Memory_map,www.embedu.org,线程间同步,同步(synchronization)指的是多个任务(线程) 按照约定的顺序相互配合完成一件事情 1968年,Edsgar Dijkstra基于信号量的概念 提出了一种同步机制 由信号量来决定线程是继续运行还是阻塞 等待,www.embedu.org,线程间同步操作,信号量代表某一类资源,其值表示系统中该资源的数量 信号量是一个受保护的变量,只能通过三种操作来访问 初始化 操作(申请资源) 操作(释放资源) 信号量的值为非负整数,www.embedu.org,线程间同步操作,() 含义如下: if (信号量的值大于0) 申请资源的任务继续运行; 信号量的值减一; else 申请资源的任务阻塞; V() 含义如下: if (没有任务在等待该资源) 信号量的值加一; else 唤醒第一个等待的任务,让其继续运行,www.embedu.org,Posix Semaphore API,posix中定义了两类信号量: 无名信号量(基于内存的信号量) 有名信号量 pthread库常用的信号量操作函数如下: int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_wait(sem_t *sem); / P操作 int sem_post(sem_t *sem); / V操作 int sem_trywait(sem_t *sem); int sem_getvalue(sem_t *sem, int *svalue);,www.embedu.org,Posix Semaphore API,www.embedu.org,Posix Semaphore API,www.embedu.org,线程同步示例(1 of 3),#include #include #include #include #include char buf60; sem_t sem; void *function(void *arg); int main(int argc, char *argv) pthread_t a_thread; void *thread_result; if (sem_init( ,www.embedu.org,线程同步示例(2 of 3),if (pthread_create( ,www.embedu.org,线程同步示例(3 of 3),void *function(void *arg) while ( 1 ) sem_wait( ,www.embedu.org,线程间互斥,引入互斥(mutual exclusion)锁的目的是用来保证共享数据操作的完整性。 互斥锁主要用来保护临界资源 每个临界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程能访问该资源 线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止,www.embedu.org,Posix Mutex API,www.embedu.org,Posix Mutex API,www.embedu.org,线程互斥示例(1 of 4),#include #include #include #include unsigned int value1, value2, count; pthread_mutex_t mutex; void *function(void *arg); int main(int argc, char *argv) pthread_t a_thread; if (pthread_mutex_init(&mutex, NULL) 0) ,www.embedu.org,线程互斥示例(2 of 4),perror(“fail to mutex_init”); exit(-1); if (pthread_create( #endif,www.embedu.org,线程互斥示例(3 of 4),value1 = count; value2 = count; #ifdef _LOCK_ pthread_mutex_unlock( #endif,www.embedu.org,线程互斥示例(4 of 4),if (value1 != value2) printf(“count=%d , value1=%d, value2=%dn”, count, value1, value2); usleep(100000); #ifdef _LOCK_ pthread_mutex_unlock( ,
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号