漫谈QNX(2)–进程,线程,同步

汽车安全 2年前 (2021) admin
764 0 0

漫谈QNX(2)--进程,线程,同步

在开始阅读之前,如果你对已介绍的内容还不了解的话,可以先阅读以下文章快速熟悉一下~

5分钟,带你了解汽车操作系统

漫谈QNX(1)–架构

漫谈QNX(2)--进程,线程,同步

进程包含一个以上的线程和许多资源

漫谈QNX(2)--进程,线程,同步

举个形象的例子:

漫谈QNX(2)--进程,线程,同步
组装线

Process来控制所有的设备(钻孔机,传送带等),每一种设备就可以想象成一个个thread。

当然还有一些更多的层级关系:

漫谈QNX(2)--进程,线程,同步

接下来两个多线程的进程的例子(multithreaded processes):

漫谈QNX(2)--进程,线程,同步
1. 一个实时性要求很高的进程和硬件进行通信,其他的线程可以慢条斯理的和其他process进行通信


漫谈QNX(2)--进程,线程,同步
2. Pool of worker threads. 很多线程准备着,当其他线程都忙的时候,新的请求依旧可以有线程来满足

一个process里的threads都有属于自己的内存地址(虚拟地址),其他的资源都是共享的。

漫谈QNX(2)--进程,线程,同步
一个process的虚拟地址

每一个thread都有一个最大的体积,也不是每一个都需要分配物理内存。

漫谈QNX(2)--进程,线程,同步

1 进程Process

fork(), exec*(), spawn(), spawn*(), posix_spawn()

举个例子fork():

漫谈QNX(2)--进程,线程,同步
fork() will create a copy of your process

fork 这个英文单词在英文里是”分叉”意思, fork() 这个函数作用也很符合这个意思. 它的作用是复制当前进程(包括进程在内存里的堆栈数据)为1个新的镜像. 然后这个新的镜像和旧的进程同时执行下去. 相当于本来1个进程, 遇到fork() 函数后就分叉成两个进程同时执行了. 而且这两个进程是互不影响.

漫谈QNX(2)--进程,线程,同步
fork

实际应用中, 单纯让程序分叉意义不大, 我们新增一个子程序, 很可能是为了让子进程单独执行一段代码. 实现与主进程不同的功能. 要实现上面所说的功能, 实际上就是让子进程和主进程执行不同的代码啊. 所以fork() 实际上有返回值, 而且在两条进程中的返回值是不同的, 在主进程里 fork()函数会返回主进程的pid, 而在子进程里会返回0! 所以我们可以根据fork() 的返回值来判断进程到底是哪个进程, 就可以利用if 语句来执行不同的代码了!

漫谈QNX(2)--进程,线程,同步

2 线程Thread

pthread_create()可以用来创建线程。

每个线程其实就是执行一个fun(). 每一个fun()就是一个thread。

pthread_create()会返回tid(thread ID).

pthread_attr_init()可以设置一个线程的default值。


如果你想设置thread优先级和调度算法:

param.sched_priority = 15; %优先级值为15
pthread_attr_setschedparam (&attr, &param); %给该thread设定优先级
pthread_attr_setschedpolicy (&attr, SCHED_RR); %设定调度算法为Round-Robin

Process里面,第一个thread就是main thread, 因为它调用了整个process的main()函数. 如果exit()被调用,那么整个process就结束死亡了。

同样的道理,如果在一个thread里, 如果pthread_exit()被调用了,那么thread也就会结束死亡。

如果一个process里面,所有的threads都死亡了,那么这个process就会死亡。

无论process如何死亡的,所有的相应的资源(内存,channels等)都会被释放或清理。

3 同步Synchronization

多threads却引入了新的问题,比如公用内存空间,多个writers可能会互相覆盖对方的值, readers也不知道什么时候数据是稳定有效地。

所以我们需要同步机制来协调管理。

3.1 Mutual exclusion

Mutual exclusion意味着只有一个thread在某一时间里可以执行某段重要的代码段,或者读写一些特别的数据。一个形象的例子:

把厕所空间比喻成内存空间,每次只能进去一个人,里面有人的时候,其他人就不能进去了。这代表一个thread使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存. 问题是如何防止别人也同时进去呢?

漫谈QNX(2)--进程,线程,同步

一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫“互斥锁”(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。

漫谈QNX(2)--进程,线程,同步
Mutex

其实我的理解就是Mutex就是一个process内的对于所有threads来说的全局01变量,你要锁的时候就把这个全局变量Mutex设置为1,其他的thread读到这个Mutex的时候就知道你在使用,就停下来等,知道你用完了把Mutex设置回0,然后别的进程才可以进去用。

当然这样又会产生新的问题,死锁问题(Dead lock). 对此,我们可以设计一些特殊的执行顺序来避免死锁,这里就不打算展开了。

当然一旦锁定了Mutex,该thread的优先级就会上升。因为系统当然希望这个thread赶紧运行完毕,毕竟不能占着茅坑不拉屎。

漫谈QNX(2)--进程,线程,同步
拥有Mutex的thread的优先级就会上升

3.2 条件锁Condvars

光有互斥锁还是不够,最好有一把聪明的互斥锁。比如说,只有满足了某种条件(收到某种信号)的情况下,才能解锁。这样就会更高效的执行程序功能。

其实总体看起来,线程的执行很像最近流行的宫廷剧里,一个皇上(CPU)拥有很多嫔妃(Threads),但是宗旨是雨露均沾。所以如何雨露均沾就是一件需要调度和协调的事情,最后还尽量要让嫔妃们都满意,苦了皇上了,哈哈。

版权声明:本文为知乎博主「强大的宇宙」原创文章


漫谈QNX(2)--进程,线程,同步

原文始发于微信公众号(Vehicle攻城狮):漫谈QNX(2)–进程,线程,同步

版权声明:admin 发表于 2021年11月18日 上午12:00。
转载请注明:漫谈QNX(2)–进程,线程,同步 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...