LINUX 进程与线程 信号量 通信
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了LINUX 进程与线程 信号量 通信,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5544字,纯文字阅读大概需要8分钟。
内容图文
操作系统 进程与线程 信号量 通信
1 进程
进程模型:每个系统有自己的虚拟CPU,但CPU又在不同进程之间进行切换。一个进程就是一个正在执行的程序,包括程序寄存器和变量当前的值。
进程是某种类型的活动,它有程序。输入和输出以及状态。单个处理器可被若干进程共享,使用某种进程调度算法,决定何时停止一个进程的工作,并转而为另一个进程提供服务。
1.1进程的创建:系统初始化,正在运行的程序执行了创建进程的系统调用,用户请求创建一个新进程,一个批处理作业初始化。父进程(英语:Parent Process)指已创建一个或多个子进程的进程。
1.2进程的终止:正常退出,出错退出,严重错误,被其他进程杀死
1.3进程的层次结构:进程和它的所有子进程以及后裔共同组成一个进程组。
Linux是一个树结构 Windows中是地位相同,每个进程地位都是相等的,句柄标识父与子进程
1.4进程的状态:运行态 就绪态,阻塞态
运行态和就绪态是由调度程序引起的,
1.5进程的实现:
2.线程
每个进程有一个进程空间和一个控制线程,在一个应用中也发生着许多活动。并行实体拥有共享同一个地址空间和所有可用数据的能力。进程比线程更轻量级,实现并行计算。
多个线程可以共享公共 内存,允许他们同时访问同一个文件夹,三个进程做不到。所有线程会有完全一样的内存空间
一个进程打开了文件,该文件对该进程中其他线程都可见
每个线程都有自己的堆栈
在用户空间中实现线程:内核对线程包一无所知,从内核角度考虑,但线程进程。用户级线程包可以在不支持线程的操作系统上实现。
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#define NUMBER_OF_THREADS 10
void *print_hello_world(void *tid)
{
printf("Hello World.Greeting from thread %d\n",tid);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[NUMBER_OF_TH];
int status,i;
for(i=0;i<NUMBER_OF_THREADS;i++)
printf();
}
进程和线程有一个关键的差别:线程完成时,把线程信息保存在线程表中,调用线程带哦都程序来选择另一个要运行的线程。不需要陷入内核,不需要上下文切换。不需要对内存告诉缓存进行刷新。
某个程序调用或者跳转到了一条不存在的内存指令上,就会发生页面故障
在内核中实现线程:
3.进程间通信
两个或多个进程写某些共享数据,最后结果取决于运行的精准时序,称为竞争条件
临界区:避免竞争条件需要的是互斥条件:确保某个进程在使用文件夹或者共享变量时候,其他进程不会进行同样的操作。共享内存进行访问的程序片段称为临界区域,适当安排,使得两个进程不可能同时处于临界区内,避免竞争条件。
忙等待的互斥:
1.屏蔽中断:每个进程刚进入临界区后立即屏蔽所有中断,并在就要离开之前再打开所有中断。CPU只有发生时钟中断时候才会进行进程切换,屏蔽后的CPU不会被切换到其他中断。缺点是对于多核处理器不能使用。
2.锁变量:检查,如果内存被占用则设为1,反之为0,0表示临界区内没有进程。但可能会发生同时进入而造成竞争条件。
3.严格轮换法:
连续测试一个变量值直到某个值出现为止,称为忙等待
两个进程严格轮流进入临界区,
while(TRUE)
{
while(turn!=0);
critical_region();
turn=1;
noncritical_region();
}
4.Peterson解法
#define FALSE 0
#define TRUE 1
#define N 2
int turn;
int interested[N];
void enter_region(int process)
{
int other;//另一个进程号
other=1-process;//另一个进程
interested[process]=TRUE;//表示感兴趣
turn =process;//设置标志
while(turn==process&&interested[other]==TRUE);//空语句
}
void leave_region(int process)
{
interested[process]=FALSE;
}
5.信号量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-prqKfDHi-1607345871930)(C:\Users\123\AppData\Roaming\Typora\typora-user-images\1603195016154.png)]
-
在缓冲区为空时,消费者不能再进行消费
-
在缓冲区为满时,生产者不能再进行生产
-
在一个线程进行生产或消费时,其余线程不能再进行生产或消费等操作,即保持线程间的同步
-
注意条件变量与互斥锁的顺序
? 因此需要保持线程间的同步,即一个线程消费(或生产)完,其他线程才能进行竞争CPU,获得消费(或生产)的机会。对于这一点,可以使用条件变量进行线程间的同步:生产者线程在product之前,需要wait直至获取自己所需的信号量之后,才会进行product的操作;同样,对于消费者线程,在consume之前需要wait直到没有线程在访问共享区(缓冲区),再进行consume的操作,之后再解锁并唤醒其他可用阻塞线程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-81HLnH8l-1607345871939)(C:\Users\123\AppData\Roaming\Typora\typora-user-images\1603195156901.png)]
假设缓冲区大小为10,生产者、消费者线程若干。生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。
-
items代表缓冲区已经使用的资源数,spaces代表缓冲区可用资源数
-
mutex代表互斥锁
-
buf[10] 代表缓冲区,其内容类型为item
-
in、out代表第一个资源和最后一个资源
var items = 0, space = 10, mutex = 1; var in = 0, out = 0; item buf[10] = { NULL }; producer { while( true ) { wait( space ); // 等待缓冲区有空闲位置, 在使用PV操作时,条件变量需要在互斥锁之前 wait( mutex ); // 保证在product时不会有其他线程访问缓冲区 // product buf.push( item, in ); // 将新资源放到buf[in]位置 in = ( in + 1 ) % 10; signal( mutex ); // 唤醒的顺序可以不同 signal( items ); // 通知consumer缓冲区有资源可以取走 } } consumer { while( true ) { wait( items ); // 等待缓冲区有资源可以使用 wait( mutex ); // 保证在consume时不会有其他线程访问缓冲区 // consume buf.pop( out ); // 将buf[out]位置的的资源取走 out = ( out + 1 ) % 10; signal( mutex ); // 唤醒的顺序可以不同 signal( space ); // 通知缓冲区有空闲位置 } }
6.调度
有多个进程同时竞争CPU,只要有两个或更多的进程处于就绪状态,这种情况就会发生。完成选择工作的这一部分程序称为调度程序,使用的算法称为调度算法。
6.1先来先服务:
6.2最短作业优先
6.3最短剩余时间优先
交互式系统中的调度:
轮转调度 优先级调度 多级调度
2.内存管理
1.地址空间
把物理地址暴露给进程会带来严重的问题:1.用户程序破坏操作系统,使得系统慢慢停止运行2.同时运行多个程序几乎不可能
多个程序同时处于内存中,不影响,需要 保护和重新定位
地址空间为程序创造了一种抽象的内存,地址空间是一个进程可用于寻址内存的一套地址集合。
基址寄存器与界限寄存器
交换技术:处理内存超载,将空闲进程存储在磁盘上。不运行时不会使用内存。分配额外内存
虚拟内存:每个进程有自己的进程空间,
内容总结
以上是互联网集市为您收集整理的LINUX 进程与线程 信号量 通信全部内容,希望文章能够帮你解决LINUX 进程与线程 信号量 通信所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。