Linux知识总结

  1. 线程

线程死锁
概念:多个线程因为竞争资源而造成的一种相互等待
原因:
1)资源不够,系统中所分配的资源不足以满足线程运行的需求,因为争夺资源造成的死锁
2)申请和释放的顺序不对
3)资源分配不当
条件:
1) 互斥:一个线程已经拥有这个资源正在运行,另外一个线程就不可以在继续使用这个资源
2) 不可剥夺:一个线程已经拥有这个资源,但是他没释放前别的线程不能使用,只能自己使用完后释放
3) 请求和保持:一个线程已经拥有了一个资源,但是他又去申请了一个新的资源,但是这个资源又被别的线程所持有。那当前的这个线程就会被阻塞,但不会放弃自己的资源
4) 循环等待:当发生死锁时,会有一个循环等待链,T0->T1,T1->Tn。
预防死锁
1) 打破互斥条件:即允许多个线程同时访问这个资源。但是也有一些资源是不被允许同时访问的。例如:打印机
2) 打破不可剥夺:即允许该线程强行的去抢占别人的资源,当这个线程拥有这个资源时,又想申请新的资源,放弃当前的这个资源,重新申请。放弃的这个资源被其他线程所访问。
3) 打破请求和保持:一次性将这个线程所需要的资源全部分配完毕,分配完毕后,在运行,这个时候就不会出现申请资源的问题。
缺点:1、占有率高、资源利用低,浪费资源。2、线程不知道自己需要多少资源,动态分配,结果不可测
4) 打破循环等待:对等待的线程进行编号,按照编号运行
在这里插入图片描述

死锁的避免
1) 安全序列
系统是安全的,是指系统中的所有进程都能够按照某一种次序分配资源,并且依次进行运行,这种进程序列{p1,p2,…….,pn}
若每一个进程,他所需要的附加资源可以被系统中所占有的资源+可用的资源之和所满足。则{p1,p2,…….,pn}是一个安全序列
2) 银行家算法
银行家算法是从当前状态出发,逐个按安全序列检查各客户谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。
死锁的检测与恢复
检测:死锁的检测与恢复是指系统设有专门的机构,当发生死锁时,这个机构能够检测到死锁发生的位置和原因,并通过外力去破坏死锁发生的必要条件,是的进程恢复过来。
恢复:
1) 系统启动—不推荐使用
2) 杀死进程,剥夺资源。

  1. 定时器

内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制
例如:电脑上设置在14:00关机,那么到了这个时间点,系统就会自动关机

  1. Alarm

Unsigned int alarm(unsigned int seconds)
函数说明:alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。
函数原型:
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
setitimer()将value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。

which参数表示类型,可选的值有:
ITIMER_REAL:以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL:以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF:以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号

struct itimerval {
struct timeval it_interval; /* 计时器重启动的间歇值 /
struct timeval it_value; /
计时器安装后首先启动的初始值 */
};

struct timeval {
long tv_sec; /* 秒 /
long tv_usec; /
微妙(1/1000000) */
};
定时器代码:
在这里插入图片描述

运行结果:
在这里插入图片描述

  1. 信号量

二进制信号量
只允许信号量取0或者1,只能被一个线程获取
整型信号量
信号量取值是整数,可以被多个线程同时获得,直到信号量变为0
记录型信号量
每个信号量s除了一个整数值外,还有一个list队列,其中是阻塞在该信号量的各个线程的标识。信号量释放一个,值+1,系统从等待队列中唤醒一个等待中的线程,让其获取信号量,信号量在-1

总结:
信号量=0,程序等待,信号量>0程序运行,信号量-1
发送信号量,信号量+1
通过对信号量的控制,实现访问顺序。
例:张三、李四、王五、赵六 4个人排队吃苹果,现在有3个苹果,张三吃了一个,苹果-1,李四吃了一个,苹果-1,王五吃了一个,苹果-1。现在剩下1个苹果,到了赵六这里,没了。赵六只有等待新的苹果了

  1. 可重入

概念:
主要用于多任务环境中,一个可重载的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制的时候不会出现什么错误
而不可重载的函数由于使用了一些系统资源,比如:全局变量区,中断向量表等,所以如果他被中断的话,可能会出现错误,这类函数是不能运行在多任务下的。
编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
编写可重入函数时,若是需要使用全局变量,则应该通过关中断、信号量操作对其保护。
问答
Q:如何编写一个可重入函数?
A:1、坚持使用全局变量;
2、不使用静态变量;
3、使用全局变量,通过信号量和关中断对其进行控制。

  1. 总线、设备、驱动
    在这里插入图片描述

注:总线(bus)设备(device)驱动(drivers)
总线是处理器与一个或者多个设备之间的通道,在设备模型中,所有的设备都通过总线相连。
设备和驱动是通过总线连接起来得,通过一个总线描述符,就可以找到挂载这条总线上的设备,以及支持该总线的不同设备驱动程序。

Struct bus_type
———————————
struct bus_type 中为devices和drivers准备了两个链表:
struct klist klist_devices
struct klist klist_drivers

struct device
———————————
struct device有两个成员
struct bus_type *bus 记录的是这个设备连在哪条总线上
struct device_driver *driver 记录的是这个设备用的是哪个驱动

struct device_driver
———————————
struct device_driver 同样有两个成员
struct bus_type *bus 代表的是这个驱动属于哪条总线
struct klist klist_devices 记录的是这个驱动支持的那些设备,没错,是devices(复数),因为一个驱动程序可以支持一个或多个设备,反过来一个设备则只会绑定给一个驱动程序.

通过定义就可以看出来:一个总线连接了一个设备和驱动,一个设备里面记录你是挂在哪条总线下,你这个设备使用的是哪个驱动,一个驱动里面记录你是属于那条总线,还有你支持那些设备。
关联:
1) 总线将设备和驱动进行绑定
2) 注册设备,匹配对应的驱动
3) 注册驱动,匹配相应的设备,这个匹配由总线来完成
4) 设与驱动的关联通过总线的match()方法进行匹配
5) 挂载驱动,匹配所有的设备,挂在设备,匹配所有的驱动。匹配成功,调用probo()函数
以注册设备为例子:
1) platform_bus_type 总线被kenrel注册
2) 系统初始化过程中调用 platform_add_devices或者platform_device_register将平台设备注册到平台总线中(platform_bus_type)
3) 平台驱动(platform driver)与平台设备(platform device)的关联是在platform_driver_register或者dirver_register中实现,这个函数在驱动的初始化过程调用。

  1. 设备树

概念
设备树描述计算机特定硬件设备信息的数据结构。以便于操作系统的内核更加方便的去管理和使用这些硬件
例:一个硬件的设备信息他就是一个设备树
优势
可以实现驱动代码与设备硬件信息的相互隔离,减少了耦合。
例:外设发生变化时,只需要查找设备树里关于外设的相关信息进行修改就好,不需要修改设备的代码
简介
dts 硬件的相关信息都写在了xxx.dts为后缀的文件中,每一款硬件有一份单独的xxxx.dts
arm架构可以在arch/arm/boot/dts找到相应的dts,另外mips则在arch/mips/boot/dts,powerpc在arch/powerpc/boot/dts。
dtsi 对于设备信息相同的dts可以封装到dtsi文件中。
在这里插入图片描述

dtc: dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具;
dtb: dts经过dtc编译之后得到dtb文件,dtb通过Boothloader引导程序加载到内核kernel。所以Bootloader需要支持设备树;Kenrel也需要加入设备树的支持
在这里插入图片描述

基本框架
• 根节点:
• 设备节点:nodex
• 节点名称:图中node;
• 节点地址:node@0就是节点的地址;
• 子节点:childnode
• 属性:属性名称(Property name)和属性值(Property value)
• 标签
在这里插入图片描述

回调函数
一般调用是从上到下一次调用,回调函数是从底层向上层调用。通过函数指针实现的,例如:camera底层需要得到app的反馈,这个时候就用到了回调,实现了功能和接口的分离。
举例:app需要打开相机,调用了底部的open方法,我们需要知道相机是否被打开,好进行下一步的操作,这个时候就需要回调了,告诉底层相机被打开了。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  1. 同步异步

同步:
在调用一个方法的时候,必须等待有返回结果的时候,才会进行下一步的执行。
异步:
在调用一个方法的时候,可以在等待结果的时候去执行别的任务,返回的结果会被通知方(被调用者或被其他方)通知调用者方法执行完毕。
例:小宝宝在睡觉,我必须守在床前等他醒来,这就是同步。小宝宝在睡觉,我去做饭,等他醒来告诉我他醒来了或者别人告诉我他醒来了。这就是异步。
阻塞:表示调用方在没有得到返回结果之前,不能去操作其他事情。
非阻塞:表示调用方在没有得到返回结果之前,可以去做其他事情,
例:小宝宝在睡觉,在他没有醒来之前,我不能去干别的事情,这就是阻塞。小宝宝在睡觉,他没有醒来的时候,我可以去看电视,耍手机,这这就是非阻塞。

  1. IO模型

1)阻塞IO
2)非阻塞IO
3)IO复用
4)信号驱动IO
5)异步IO
IO复用
select用法:
linux系统提供select函数来实现多路复用,select系统调用是用来让我们的应用程序监视多个文件句柄的状态变化,程序会在select这里等待,直到被监视的文件句柄有一个或多个发生了状态如可读或可写。
函数原型:
***int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ***
n是最大文件描述符+1,既STDIN_FILENO+1该值会有限制,一般是1024,所以生产环境使用epoll,kqueue代替
readfds 监视是否有可读文件的描述符集合
writefds 监视是否有可写文件的描述符集合
exceptfds 监视是否有异常情况的文件符描述集合。
Timeout 超时时间
poll
epoll
int epoll_create(int size);
创建epoll实例,size大于0,内核会获取大小,函数返回epoll本身的描述符。
*int epoll_ctl(int epfd, int op, int fd, struct epoll_event event);
添加,修改,删除要监听的event事件,op –》add添加,MOD修改,del删除
*int epoll_wait(int epfd, struct epoll_event events, int maxevents, int timeout);
epoll_wait用于监视等待是否有IO事件发生,直到timeout过期

  1. 字符设备与块设备

字符设备
字符设备是像字符一样被访问的设备,以字节为单位进行读写。一般来说对硬件IO的操作可以归于字符设备。字符设备是按照顺序访问的,不支持随机,每个字符设备在/dev目录下对应一个设备文件。LInux用户程序通过设备文件(设备节点)来使用驱动程序操作字符设备。
常见的字符设备有:鼠标/键盘/led/串口/控制台
设备
块设备是通过内存缓存区访问的,以数据块的形式存放设备。支持随机(会读取一定长度的内容,而只返回用户要求的内容,所以随机访问还是读取的全部内容)一般理解为存储🥱介质类。每个块设备在/dev目录下对应一个设备文件。LInux用户程序通过设备文件(设备节点)来使用驱动程序操作字符设备。块设备可以容纳文件系统,一般是通过文件系统来访问,而不是/dev下的节点。
例:硬盘/光盘/TF卡

进程间的通信:
管道/socket/消息队列message/信号/共享内存/信号量
线程同步:
互斥锁/读写锁/条件变量/信号量/自旋锁/屏障
IO复用3种方式
https://www.jianshu.com/p/ed1f9e9a1982

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值