linux多线程编程ppt
Linux课件 进程线程编程.ppt
45
其中kill的参数pid>0是将信号发送到PID 为pid的进程;
pid=0将信号发送到与发送进程处于同一 进程组的进程;
pid<-1将信号发送到进程组ID等于-pid的 所有进程;
pid=-1 POSIX未指定,Linux发送到进程 表中所有的进程(除第一个进程之外)。
41
(3) 信号控制函数 (a) 捕捉信号
此函数是信号处理程序或者信号捕捉函数。 它可以决定系统对信号的响应。 void (*signal (int signo,void (*func)(int)))(int)
42
其中signo是表1-1中的信号名; func的值是SIG_IGN或SIG_DFL或者 是接到此信号后需要调用的函数地址。
29
进程创建时的状态为 UNINTERRUPTIBLE,在fork()结束前被父进 程唤醒后,变为RUNNING。
处于RUNNING状态的进程被移到就绪队 列中,在适当时候由schedule()按处理机调度 算法选中,获得处理机。
30
获得处理机而正在运行的进程若申请不到 某个资源,则调用sleep()进行休眠,其PCB 挂到相应的等待队列,状态变为
即使是在多处理机的系统中,Linux也只 能同时让一个处理机执行任务。
22
◆ UNINTERRUPTABLE: 不可中断阻塞状态。 处于这种状态的进程正在等待队列中,
当资源有效时,可由操作系统进行唤醒, 否则,将一直处于等待状态。
23
◆ INTERRUPTABLE: 可中断阻塞状态。 与不可中断阻塞状态一样,处于这种状
信号发生时,内核中断当前的进程,进 程执行处理函数来响应信号,结束后恢复正 常的进程处理。
linux进程和线程编程教学课件
进程和线程的用户管理
01
用户注册、权限管理、登录与会话、作业控制等概念及流程。
02
用户切换、进程组、会话组等概念及其在用户管理中的作用。
进程和线程的用户权限管理:setuid、setgid等权限控制手段
03
的原理和使用。
进程和线程的系统调用
01
系统调用概念及作用
系统调用在操作系统中的作用及基本 原理。
进程是系统资源分配 和隔离的单位,每个 进程都有独立的地址 空间和系统资源
进程之间的通信需要 通过IPC(进程间通 信)机制实现,如管 道、消息队列、共享 内存等
进程是独立的执行实 体,拥有自己的系统 资源和地址空间,可 以独立运行
在多任务环境下,多 进程可以更好地隔离 和征
独立性、动态性、并发性、异步性、共享性。
进程状态
3
就绪状态、执行状态、阻塞状态、等待状态。
什么是线程
线程定义
线程是操作系统能够进行运算 调度的最小单位,是进程内的
一个执行路径。
线程特征
轻量级、可并发性、共享性、动 态性、独立性。
线程状态
新建、就绪、运行、阻塞、终止。
进程和线程的关系
进程和线程都属于操作系统的 基本概念,是系统资源分配的 基本单位。
linux进程和线程编程教学课件
xx年xx月xx日
目录
• linux进程和线程基础 • linux进程控制 • linux线程控制 • linux进程和线程管理 • linux进程和线程编程实例
01
linux进程和线程基础
什么是进程
1 2
进程定义
进程是计算机中的程序关于某数据集合上的一 次运行活动,是系统进行资源分配和调度的基 本单位。
第9章多线程编程PPT课件
➢ pthread_join()可以用于将当前线程挂起来等待线程的结束。这个 函数是一个线程阻塞的函数,调用它的函数将一直等待到被等 待的线程结束为止,当函数返回时,被等待线程的资源就被收 回。
➢ Linux2.4内核消除了这个线程个数的限制,并且允许在系统运行 中动态地调整进程数上限。采用的是LinuxThread线程库,它对 应的线程模型是“一对一”线程模型,也就是一个用户级线程 对应一个内核线程,而线程之间的管理在内核外的函数库中实 现。
➢ 在Linux 内核2.6之前的版本中,进程是最主要的处理调度单元, 并没支持内核线程机制。Linux 2.6内核支持clone()系统调用,从 而实现共享地址空间的进程机制。因而Linux系统在1996年第一 次获得线程的支持,当时所使用的函数库被称为LinuxThread。 该函数库就使用clone()系统调用实现内核级的线程机制,在此前 的Linux版本中在用户层实现POSIX线程库。
➢ 轻量级进程:内核支持的用户线程,是内核线程的一种抽 象对象。
➢ 内核线程:允许不同进程中的线程按照同一相对优先调度 方法进行调度,这样就可以发挥多处理器的并发优势。
➢ 现在大多数系统都采用用户级线程与核心级线程并存的方 法。
Linux线程技术的发展
➢ 在Linux2.2内核中,并不存在真正意义上的线程。当时Linux中常 用的线程pthread实际上是通过进程来模拟的,并且线程的个数 也有限,最多只能有4096个进程/线程同时运行。
Linux下多线程编程PPT教学课件
2020/12/10
5
简单的多线程编程
编译此程序:
gcc example1.c -lpthread -o example1
运行example1,我们得到如下结果:
This is the main process. This is a pthread. This is the main process. This is the main process. This is a pthread. This is a pthread.
NULL,这个值将被传递给 thread_return。
2020/12/10
8
修改线程的属性
在上一节的例子里,我们用pthread_create函数创建了一个线程,在这个线程中, 我们使用了默认参数,即将该函数的第二个参数设为NULL。对大多数程序来说,使 用默认属性就够了,但我们还是有必要来了解一下线程的有关属性。
2020/12/10
4
简单的多线程编程
int main(void) {
pthread_t id; int i,ret; ret=pthread_create(&id,NULL,(void *) thread,NULL); if(ret!=0){
printf ("Create pthread error!n"); exit (1); } for(i=0;i<3;i++) printf("This is the main process.n"); pthread_join(id,NULL); return (0); }
这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当 函数返回时,被等待线程的资源被收回。
多核程序设计课件4-Linux多线程编程
在Linux中,线程一般被认为是“轻量级的进程”。 Linux 创建进程所使用的函数是fork() 或者vfork()。而对线程的 创建和管理,Linux可以使用POSIX的线程库pthreads提供的APIs。
Linux提供的多线程和多进程执行环境主要目的是提高系统资源利用 率和任务的并发或并行程度。
void * arg);
第一个参数是pthread_t 类型的指针,这个指针指向用来存 放当线程创建成功后的所创建的线程的标志 第二个参数表明被创建的线程可以拥有的属性 第三个参数是一函数指针,此函数指针指向线程的实现函数 第四个参数arg是void *类型的,此参数指向实际线程处理 函数执行的时候所需要的参数
线程的撤销(续)
使用线程撤销相关的操作的例子
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #define THREAD_NUMBER 2 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_t pt[THREAD_NUMBER]; void* thread1(void *arg) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); pthread_mutex_lock(&mutex); sleep(5); printf("now thread1 is in cancelation point\n"); /* pthread_cond_wait 是一撤销点,thread1 在这里等待条件变量的满足 */ pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); pthread_exit(NULL); }
Linux多线程编程讲稿
而运行于一个进程中的多个线程,它们彼此之间使用相同的 地址空间,共享大部分数据,启动一个线程所花费的空间远 远小于启动一个进程所花费的空间,而且,线程间彼此切换 所需的时间也远远小于进程间切换所需要的时间。
© 2007 博创科技
博创科技 嵌入互动
进程与线程(二)
使用多线程的理由之二是线程间方便的通信机制。
© 2007 博创科技
博创科技 嵌入互动
#include <pthread.h> #include <sched.h> pthread_attr_t attr; pthread_t tid; sched_param param; int newprio=20; pthread_attr_init(&attr); pthread_attr_getschedparam(&attr, ¶m); param.sched_priority=newprio; pthread_attr_setschedparam(&attr, ¶m); pthread_create(&tid, &attr, (void *)myfunction, myarg);
© 2007 博创科技
博创科技 嵌入互动
互斥锁
互斥锁用来保证一段时间内只有一个线程在执行一 段代码 看下面一段代码。这是一个读/写程序,它们公用一 个缓冲区,并且假定一个缓冲区只能保存一条信息。 即缓冲区只有两个状态:有信息或没有信息。
© 2007 博创科技
博创科技 嵌入互动
void reader_function ( void ); void writer_function ( void ); char buffer; int buffer_has_item=0; pthread_mutex_t mutex; struct timespec delay;
8第八讲 Linux进程通信及多线程课件
2021/6/28
北京理工大学珠海学院 计算机教研室
16
2021/6/28
注意:FIFO是严格的遵循先进先出规则,对管道及FIFO的读总是从开 始出返回数据,对它们的写则是把数据添加到末尾,不支持lseek()等文 件定位操作
有名管道的创建可以使用函数mkfifo(),该函数类似文件中的open()操作, 可以指定管道的路径和打开的模式
BSD跳过上述限制,形成了基于套接口(socket)的进程间 通信机制
Linux把两者的优势都继承下来
UNIX进程间通信(IPC)方式包括管道、FIFO、信号 System V进程间通信(IPC)包括System V消息队列、System V信
号灯、System V共享内存区 Posix进程间通信(IPC)包括Posix消息队列、Posix信号灯、Posix
标准流管道 read,write一类不带缓冲的I/O函数
函数说明
与Linux中文件操作有基于文件流的标准I/O操作一样,管道的操 作也支持基于文件流的模式
这种模式的管道主要是用来创建一个连接到另一个进程的管道
所完成的工作有以下几步:
2021/6/28
北京理工大学珠海学院 计算机教研室
14
▪ 创建一个管道 ▪ fork一个子进程 ▪ 在父子进程中关闭不需要的文件描述符 ▪ 执行exec函数族调用 ▪ 执行函数中所指定的命令
对于写进程
▪ 若该管道是阻塞打开,则写进程将一直阻塞直到读进程读出数据
▪ 若该管道是非阻塞打开,则当前FIFO内没有操作,写进程会立即执
行读操作
北京理工大学珠海学院 计算机教研室
17
函数格式
所需头文件 #include <sys/types.h>
跟我学linux编程-12-多线程编程-同步
多线程编程-同步在上一章节中,我们通过程序示例,见证了单线程世界中不可能发生的事件(一个数既是奇数又是偶数)在多线程环境中是怎样分分钟发生的,我通过细分程序执行步骤,分析了奇异事件发生的过程,并探明了其原因:一个线程在对全局变量gcnt进行两次判读的过程中,另一个线刚好改变了这个变量的值。
在多线程编程术语中,称这两个线程同时进入了临界区域。
所谓临界区域,是指多线程环境下两个及以上线程同时执行可能会导致冲突的一段代码。
在上一章节的示例中,这几行代码就是一个临界区域:gcnt++;if (gcnt % 2){if (!(gcnt % 2)) printf("[%d] : %d\n", id, gcnt);}冲突之所以会发生,是因为临界区域的代码,通常需要很多个CPU指令周期才能完成,其运行过程随时可能被打断(进行了线程调试),CPU去运行另外的线程,如果这个线程刚好也进入了临界区域,则异常的程序状态极可能会发生。
如果当某个线程进入临界区域,在其退出区域之前,其他的线程无论如何也不能进入该区域,那么冲突就不会发生。
Linux提供了这种保证多线程进入临界区域互斥的机制,这正是本章节所要介绍的内容:线程锁。
我们今天的示例程序还是在上一章节的示例上改进而来的,我们的任务就是使用线程锁,保证“一个数既是奇数又是偶数”的奇异事件在多线程环境下也不发生,代码如下:#include <pthread.h>#include <stdio.h>#include <unistd.h>int gcnt = 0;pthread_mutex_t g_mutex;void *thread_task(void *arg){int id = (int)arg;while (1){pthread_mutex_lock(&g_mutex);gcnt++;if (gcnt % 2)if (!(gcnt % 2)) printf("[%d] : %d\n", id, gcnt);}pthread_mutex_unlock(&g_mutex);usleep(1);}return NULL;}int main(int argc, char *argv[]){pthread_t thr;pthread_mutex_init(&g_mutex, NULL);pthread_create(&thr, NULL, thread_task, (void *)1);pthread_create(&thr, NULL, thread_task, (void *)2);thread_task((void *)0);return 0;}今天的程序相对于上章的代码,改动非常小,只添加了四行,已使用红色加粗标注。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
互斥锁线程控制 (2)
其中,互斥锁可以分为快速互斥锁、递归互斥锁和检错互 斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程 在希望得到互斥锁时是否需要阻塞等待。快速锁是指调用 线程会阻塞直至拥有互斥锁的线程解锁为止。递归互斥锁 能够成功地返回,并且增加调用线程在互斥上加锁的次数, 而检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返 回并返回一个错误信息。默认属性为快速互斥锁。
线程机制的分类和特性 (2)
(3)内核线程
这种线程允许不同进程中的线程按照同一相对优先调度 方法进行调度,这样就可以发挥多处理器的并发优势。 现在大多数系统都采用用户级线程与核心级线程并存的 方法。一个用户级线程可以对应一个或几个核心级线程, 也就是“一对一”或“多对一”模型。这样既可满足多 处理机系统的需要,也可以最大限度地减少调度开销。 使用线程机制大大加快上下文切换速度而且节省很多资 源。但是因为在用户态和内核态均要实现调度管理,所 以会增加实现的复杂度和引起优先级翻转的可能性。一 个多线程程序的同步设计与调试也会增加程序实现的难 度。
Linux线程技术的发展 (1)
在Linux2.2内核中,并不存在真正意义上的线程。当时 Linux中常用的线程pthread实际上是通过进程来模拟的,也 就是说Linux中的线程也是通过fork()创建的“轻”进程, 并且线程的个数也很有限,最多只能有4096个进程/线程同 时运行。 在Linux2.2内核中,并不存在真正意义上的线程。当时 Linux中常用的线程pthread实际上是通过进程来模拟的,也 就是说Linux中的线程也是通过fork()创建的“轻”进程, 并且线程的个数也很有限,最多只能有4096个进程/线程同 时运行 。
Linux线程技术的发展 (3)
为了改善LinuxThread问题,出现根据新内核机制重新编写 线程库的问题。许多项目在研究如何改善Linux对线程的支 持,其中两个最有竞争力的有由IBM主导的新一代POSIX 线程库(Next Generation POSIX Threads,简称为NGPT) 和由Red Hat主导的本地化POSIX线程库 (Native POSIX Thread Library,简称为NTPL)。 NGPT项目在2002年启动,但为了避免出现有多个Linux线 程标准,所以在2003年停止该项目。与此同时NPTL问世, 最早在Red Hat Linux9中被支持,现在已经成为GNU C函 数库的一部分,同时也成为Linux线程的标准。
信号量线程控制 (2)
开始 开始 初始化信号量 sem1 为1, sem2为0
初始化信号量为1
P操作
P操作
P操作sem1
P操作sem2
线程一执行
线程二执行
线程一执行
线程二执行
V操作
V操作
V操作sem2
V操作sem1
结束
信号量的互斥
结束
信号量的同步
本章的要求
第9章、多线程编程
掌握Linux中线程的基本概念 掌握Linux中线程的创建及使用 掌握Linux中线程属性的设置 能够独立编写多线程程序 能够处理多线程中的同步与互斥问题
本章的主要内容
9.1 Linux线程概述 9.2 Linux线程编程 9.3 实验内容——“生产者消费者”实验
信号量线程控制 (4)
示例
阅读并运行9-2-3。
பைடு நூலகம்
线程属性 (1)
绑定属性 Linux中采用“一对一”的线程机制,也就是一个用户线程对应 一个内核线程。绑定属性就是指一个用户线程固定地分配给一 个内核线程,因为CPU时间片的调度是面向内核线程(也就是 轻量级进程)的,因此具有绑定属性的线程可以保证在需要的 时候总有一个内核线程与之对应。而与之对应的非绑定属性就 是指用户线程和内核线程的关系不是始终固定的,而是由系统 来控制分配的。 分离属性 分离属性是用来决定一个线程以什么样的方式来终止自己。在 非分离情况下,当一个线程结束时,它所占用的系统资源并没 有被释放,也就是没有真正的终止。只有当pthread_join()函数返 回时,创建的线程才能释放自己占用的系统资源。而在分离属 性情况下,一个线程结束时立即释放它所占有的系统资源。这 里要注意的一点是,如果设置一个线程的分离属性,而这个线 程运行又非常快,那么它很可能在pthread_create()函数返回之前 就终止了,它终止以后就可能将线程号和系统资源移交给其他 的线程使用。
信号量线程控制 (3)
sem_init()用于创建一个信号量,并初始化它的值。 sem_wait()和sem_trywait()都相当于P操作,在信号量大 于零时它们都能将信号量的值减一,两者的区别在于若 信号量小于零时,sem_wait()将会阻塞进程,而 sem_trywait()则会立即返回。 sem_post()相当于V操作,它将信号量的值加一同时发出 信号来唤醒等待的进程。 sem_getvalue()用于得到信号量的值。 sem_destroy()用于删除信号量。
9.1 Linux线程概述
线程概述(1)
前面已经提到,进程是系统中程序执行和资源分配的基本 单位。每个进程都拥有自己的数据段、代码段和堆栈段, 这就造成了进程在进行切换等操作时都需要有比较复杂的 上下文切换等动作。为了进一步减少处理机的空转时间, 支持多处理器以及减少上下文切换开销,进程在演化中出 现了另一个概念——线程。它是进程内独立的一条运行路 线,处理器调度的最小单元,也可以称为轻量级进程。线 程可以对进程的内存空间和资源进行访问,并与同一进程 中的其他线程共享。因此,线程的上下文切换的开销比创 建进程小很多。 同进程一样,线程也将相关的执行状态和存储变量放在线 程控制表内。一个进程可以有多个线程,也就是有多个线 程控制表及堆栈寄存器,但却共享一个用户地址空间。要 注意的是,由于线程共享了进程的资源和地址空间,因此, 任何线程对系统资源的操作都会给其他线程带来影响。由 此可知,多线程中的同步是非常重要的问题。
9.2 Linux线程编程
线程基本编程 (1)
创建线程实际上就是确定调用该线程函数的入口点,这里 通常使用的函数是pthread_create()。在线程创建以后,就 开始运行相关的线程函数,在该函数运行完之后,该线程 也就退出了,这也是线程退出一种方法。另一种退出线程 的方法是使用函数pthread_exit(),这是线程的主动行为。 由于一个进程中的多个线程是共享数据段的,因此通常在 线程退出之后,退出线程所占用的资源并不会随着线程的 终止而得到释放。正如进程之间可以用wait()系统调用来同 步终止并释放资源一样,线程之间也有类似机制,那就是 pthread_join()函数。pthread_join()可以用于将当前线程挂起 来等待线程的结束。这个函数是一个线程阻塞的函数,调 用它的函数将一直等待到被等待的线程结束为止,当函数 返回时,被等待线程的资源就被收回。
Linux线程技术的发展 (2)
Linux2.4内核消除了这个线程个数的限制,并且允许在系 统运行中动态地调整进程数上限。当时采用的是 LinuxThread线程库,它对应的线程模型是“一对一”线程 模型,也就是一个用户级线程对应一个内核线程,而线程 之间的管理在内核外的函数库中实现。 在Linux 内核2.6之前的版本中,进程是最主要的处理调度 单元,并没支持内核线程机制。Linux 2.6内核支持clone() 系统调用,从而实现共享地址空间的进程机制。因而Linux 系统在1996年第一次获得线程的支持,当时所使用的函数 库被称为LinuxThread。该函数库就使用clone()系统调用实 现内核级的线程机制,在此前的Linux版本中在用户层实现 POSIX线程库。
线程概述(2)
进程 用户地址空间
线程一
线程二
线程三
线程机制的分类和特性 (1)
(1)用户级线程 用户级线程主要解决的是上下文切换的问题,它的调度算 法和调度过程全部由用户自行选择决定,在运行时不需要 特定的内核支持。在这里,操作系统往往会提供一个用户 空间的线程库,该线程库提供了线程的创建、调度和撤销 等功能,而内核仍然仅对进程进行管理。如果一个进程中 的某一个线程调用了一个阻塞的系统调用函数,那么该进 程包括该进程中的其他所有线程也同时被阻塞。这种用户 级线程的主要缺点是在一个进程中的多个线程的调度中无 法发挥多处理器的优势。 (2)轻量级进程 轻量级进程是内核支持的用户线程,是内核线程的一种抽 象对象。每个线程拥有一个或多个轻量级线程,而每个轻 量级线程分别被绑定在一个内核线程上。
线程基本编程 (3)
线程基本编程 (4)
示例
阅读并运行示例9-2-1
互斥锁线程控制 (1)
互斥锁是用一种简单的加锁方法来控制对共享资源的原子 操作。这个互斥锁只有两种状态,也就是上锁和解锁,可 以把互斥锁看作某种意义上的全局变量。在同一时刻只能 有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对 共享资源进行操作。若其他线程希望上锁一个已经被上锁 的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互 斥锁为止。可以说,这把互斥锁保证让每个线程对共享资 源按顺序进行原子操作。 互斥锁机制主要包括下面的基本函数。 互斥锁初始化:pthread_mutex_init() 互斥锁上锁:pthread_mutex_lock() 互斥锁判断上锁:pthread_mutex_trylock() 互斥锁接锁:pthread_mutex_unlock() 消除互斥锁:pthread_mutex_destroy()