【操作系统作业-lab4】 linux 多线程编程和调度器
linux多线程编程
参考:https://blog.csdn.net/weibo1230123/article/details/81410241
https://blog.csdn.net/skyroben/article/details/72793409
1.背景知识
Linux没有真正意义上的线程,它的实现是由进程来模拟,所以属于用户级线程,位于libpthread共享库(所以线程的ID只在库中有效),遵循POSIX标准。
Linux上两个最有名的线程库LinuxThreads和NPTL。两个线程模型的比较:https://www.ibm.com/developerworks/cn/linux/l-threading.html
2.线程控制
在linux系统下,线程相关的函数都定义在pthread.h头文件中
创建线程函数-------pthread_creat函数
#include<pthread.h>
int pthread_creat(pthread_t thread, const pthread_attr_t* attr, void*(*start_routin)(void *), void* arg);
参数解释
* thread参数是新线程的标志符,为一个整型。
* attr参数用于设置新线程的属性。给传递NULL表示设置为默认线程属性。
* start_routin和arg参数分别指定新线程将运行的函数和参数。start_routin返回时,这个线程就退出了
* 返回值:成功为0,失败返回错误号
线程id的类型是pthread_t,它只在当前进程中保证是唯一的,在不同的系统中pthread_t可能有不同的实现,调用pthread_self()可以获取当前进程的id。
进程id的类型时pid_t,每个进程的id在整个系统中是唯一的,调用getpid()可以获得当前进程的id,是一个正整数值。
终止线程-------pthread_exit() 函数和 pthread_cancel()函数
终止某个线程而不是终止一个进程,可以可以有三种方法:
1.从线程函数return,在creat时候的第三个参数。这种方法对主线程不适应,从main函数return相当于调用exit。
2.一个线程可以调用Pthread_cancle终止同一进程中的另一个线程。
3.线程可以调用pthread_exit终止自己
#include<pthread.h>
int pthread_cancle(pthread_t thread);
*thread 是线程标识符
*该函数成功返回0,失败返回错误码
#include<pthread.h>
void pthread_exit(void *reval);
*retral 是void*类型,其他线程可以调用Pthread_join获得这个指针。需要注意,需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是由malloc分 配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。
*pthread_exit函数通过retval参数向线程的回收者传递其退出的消息。它执行之后不会返回到调用者,且永远不会失败。
线程等待-----pthread_join
#include<pthread.h>
void pthread_join(pthread_t thread, void ** retval)
*调用该函数的线程将挂起等待,知道id为thread的线程终止
*thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的
3.分离线程
1.在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached)。
2.一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源
(例如栈)是不释放的。(默认情况下线程的创建都是可结合的)
3.一个分离的线程是不能被其他线程回收或杀死的,它的存储器 资源在它终止时由系统自动释放。
4. 如果一个可结合线程结束运行但没有被join,会导致部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源。
linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。
unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。或者将线程置为 joinable,然后适时调用pthread_join.
其实简单的说就是在线程函数头加上 pthread_detach(pthread_self())的话,线程状态改变,在函数尾部直接 pthread_exit线程就会自动退出.
实例:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5 struct msg{
int id;
char* word;
}; //thread要运行的方法
void PrintHello(struct msg* arg)
{
printf("%s%d!\n", arg->word, arg->id);
arg->id=;
pthread_exit(NULL);
} int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
//创建线程id
struct msg arg[NUM_THREADS];
//创建msg数组群
char* word = "Hello World! It's me, thread #"; //分别创建5个线程
for(int t=;t<NUM_THREADS;t++){
printf("In main: creating hread %d\n", t)t;
arg[t] = (struct msg){t, word};
pthread_create(&threads[t], NULL, &PrintHello, &arg[t]);
//arg作为参数传入新线程运行的函数PrintHello里,四个参数分别是线程id,默认格式,线程运行的函数,函数参数。函数结束及新线程结束运行
} //让主线程依次等待各个线程执行完各自的函数后结束主线程
for(int t=;t<NUM_THREADS;t++)
pthread_join(threads[t], NULL);//主线程挂起等待直到调用的函数结束
printf("\nall threads finish.\n");
/* Last thing that main() should do */
pthread_exit(NULL);//主线程终止自己
}
OS 调度器
1.几个概念
Program: a group of instructions to carry out a specified task
--stored on disk in some file
Process: an execution of certain program with its own address space and control of one or more threads
--resources: CPU, memory address, disk, IO ...
--one program can invoke multipleprocesses
Thread: the unit of execution in CPU
Job: a series of program submitted to operating system for some goals
2.背景信息
OS 有三种进程调度队列:Job Queue,Ready Queue,DeviceQueue
Job Queue:进程都被存储在外部存储里,还未被唤醒的进程们。
Ready Queue:process 已经准备好 并且等待CPU来运行它们 , 存储在main memory里面
Device Queue:一个IO waitting queue,等待IO所以暂时让出CPU,blocked processes stored
multiprogramming 的degree: the number of processes in memory
IO-bound process : spends more time doing I/O than doing computations
CPU-bound process:doing I/O infrequently but using more time on computations
3. 调度系统
一个作业(job)提交到操作系统后,将经历三种调度:
-长期调度程序 long-term scheduler
-中期调度程序 medium-term scheduler
-短期调度程序 short-term scheduler
-长期调度程序 long-term scheduler:
选择disk里的进程,load 到ready queue里,选择时考虑IO-bound 和 CPU-bound
调度器出现在job queue --->ready queue里面
-短期调度程序 short-term scheduler(也叫CPU scheduler)
从ready queue里选择一个process,放到CPU里运行。
调度器出现在ready queue到CPU的进度里,此处可以执行的调度算法有SJF,RR,priority等
-中期调度程序 medium-term scheduler(也叫swapping scheduler)
swap一个process(或者是IO bound或者是CPU bound)出CPU,back into memory
调度器出现在cpu--ready queue || job queue
三个调度系统的比较:
4.被CPU安排的进程的一生:
【操作系统作业-lab4】 linux 多线程编程和调度器的更多相关文章
- Linux多线程编程初探
Linux线程介绍 进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程 ...
- ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程
为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...
- Linux多线程编程之详细分析
线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我见到这样一道面试题: 是否熟悉POSIX多线程 ...
- Linux多线程编程和Linux 2.6下的NPTL
Linux多线程编程和Linux 2.6下的NPTL 在Linux 上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程.一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构, ...
- Linux多线程编程小结
Linux多线程编程小结 前一段时间由于开题的事情一直耽搁了我搞Linux的进度,搞的我之前学的东西都遗忘了,非常烦躁的说,如今抽个时间把之前所学的做个小节.文章内容主要总结于<Linux程序 ...
- Linux多线程编程阅读链接
1. 进程与线程的一个简单解释(阮一峰) 2. linux 多线程编程 3. Linux 的多线程编程的高效开发经验 (IBM)
- Linux多线程编程实例解析
Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...
- Linux多线程编程(不限Linux)【转】
——本文一个例子展开,介绍Linux下面线程的操作.多线程的同步和互斥. 前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步 ...
- Linux多线程编程(不限Linux)
前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我在某QQ群里见到这样一道面试题: 是否熟 ...
随机推荐
- POJ 3164——Command Network——————【最小树形图、固定根】
Command Network Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 15080 Accepted: 4331 ...
- Linux 启动盘命令
linux下有很多工具可以制作启动盘, 例如 unetbootin 和 wubi, 不过我们可以使用linux下的一条命令来完成-----dd 操作方法: 1 卸载你的U盘 假设你的u盘对应的设备是s ...
- Java学习笔记--继承和多态(下)
1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toStrin ...
- C#继承 多态
1.继承 允许我们根据一个类来定义另一个类.已有的类被称为的基类(父类),新的类被称为派生类(子类). 单一继承:只能有一个基类,一个基类可以派生出多个派生类,一个类别只可以继承自一个父类. 多重继承 ...
- oracle账户密码过期,修改为无限制
查看用户的proifle是哪个,一般是default: sql>SELECT username,PROFILE FROM dba_users; 查看指定概要文件(如default)的密码有效期设 ...
- Mysql 求时间 between 昨天 and 上个月的今天 等时间函数
问题: Mysql表中一列create_time,类型datetime(YYYY-MM-DD HH:MM:SS),想获取上个月今天到昨天的数据. select * from 表名 where date ...
- [JAVA][Liferay] Duplicate key value violates unique constraint for resourcepermissionid in Liferay
Unexpected exception thrown when create new site: 09:47:10,114 ERROR [ajp-bio-8009-exec-113][JDBCExc ...
- iframe跨域上传图片
方案一:用jquery的$.post异步提交,然后把返回来的值用jquery填充到隐藏域中.可是$.post不支持跨域. jQuery.ajax()支持get方式的跨域,这其实是采用jsonp的方式来 ...
- hibernate 模拟实现和What is and Why O/R Mapping
What is and Why O/R Mapping What is : 用面向对象的方式调用api,类库帮我们翻译成面向关系的方式. Why: 1.JDBC操作数据库很繁琐2.Sql 语句编写并不 ...
- js call(),apply(),对象冒充,改变变量作用域
1.apply(); function box(n1,n2){ return n1+n2; } function pox(n1,n2){ alert(box.apply(this,[n1,n2])); ...