Linux操作系统学习
2021-03-04 17:49:28 0 举报
AI智能生成
Linux操作系统学习
作者其他创作
大纲/内容
3. 内核编程
内核的同步方法
原子操作
atomic_t
自旋锁 spin lock
空转一会儿
下半部经常使用这个锁
读-写锁
信号量
一种特殊的睡眠锁
互斥体
java的synchronized的重量级锁
mutex
mutex_init()
mutex_lock()
mutex_unlock()
屏障
简单操作命令
文件与目录
列出目录
隐藏文件页一起列出来
ls -a
长数据串列出,包含文件的属性与权限等等数据
ls -a(简写为ll)
切换目录
切换绝对目录
cd /usr/local
切换相对目录
cd ./local
显示目前文件所在的目录
pwd
创建新目录
创建一个目录
mkdir test
创建多层目录
mkdir -p /test/test1/test2
创建test,并通过-m指定目录的权限
mkdir -m 711 test
给文件复制权限
chmod -R 777 tomcat-cluster
删除目录
删除单个目录
rmdir test
删除多级目录
rmdir test/test2/test3
复制文件或目录
复制所有的文件
cp -r test/* /usr/local/nginx/html
移除文件或目录
不询问删除
rm 文件或目录
询问删除
rm -i 文件或目录
移动文件或目录
修改名字
mv wenjian1 wenjian2
移动文件
mv -r test1/* test2
查看文件的权限
ls -lrt
给文件/文件夹赋权限
chmod 777 文件/文件夹
创建文件
touch
查看文件详细信息
stat
chown
改变文件所属用户
chgrp
改变文件所属组
wget
下载文件
grep
搜索文件
more/less
部分显示
用户组
每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建
groupadd
新建用户组
groupadd <选项>
groupadd group1
此命令向系统中增加了一个新组group1
新组的组标识号是在当前已有的最大组标识号的基础上加1
-g
groupadd -g
groupadd -g 101 group2
此命令向系统中增加了一个新组group2,同时指定新组的组标识号是101。
-o
一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同
groupdel
删除用户组
groupde
groupdel
groupdel group1
newgrp
用户可以在用户组之间切换
newgrp
newgrp root
将当前用户切换到root用户组
用户
useradd
新建用户
useradd <选项>
useradd sun
新建用户sun
-c
useradd -c <描述内容> sun
指定一段注释性描述
useradd -c "admin" sun
-d
useradd -d <用户主目录>
useradd –d /usr/sam -m sam
此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录/usr/sam(/usr为默认的用户主目录所在的父目录)。
-g
useradd -g
useradd -g group1 sun
指定用户所属的用户组
-u
指定用户号
userdel
删除帐号
userdel <选项>
userdel sun
-r
userdel -r
把用户的主目录一起删除
userdel -r sam
此命令删除用户sam在系统文件中(主要是/etc/passwd, /etc/shadow, /etc/group等)的记录,同时删除用户的主目录
usermod
修改与用户有关属性,如用户号、主目录、用户组、登录Shell等
-c
usermod -c <描述内容>
usermod -c "test" sun
修改用户的描述信息
-d
usermod -d <新的用户主目录>
修改用户所属主目录
-g
usermod -g <用户组>
修改用户所属的组
-G
usermod -G <用户附加组>
修改用户所属的附加组
-s
修改用户登录Shell
-u
修改用户号
-o
可重复使用用户的标识号
passwd
用户口令
passwd <选项>
passwd
当前为普通用户,修改当前用户的口令
passwd
当前为超级用户,修改其它用户的密码
passwd -l
锁定口令,即禁用账号
passwd -u
口令解锁
passwd -d
使账号无口令
passwd -f
强迫用户下次登录时修改口令
切换帐户
su -
auth
项目常用命令
mysql
登录
mysql -h192.168.0.1 -uroot -proot -P3306
开启/关闭/重启
通过rpm包安装的
service mysqld start/stop/restart
linux通过源码包安装(开启)
$mysql_dir/bin/mysqld_safe &
其他
/etc/inint.d/mysqld start/stop/restart
在windows
开启,在bin目录下
net start mysql
关闭,在bin目录下(无密码)
net stop mysql
关闭,在bin目录下(有密码)
mysqladmin -u root -p shutdown
修改密码
mysqladmin -u用户名 -p旧密码 password 新密码
关闭
通过源码包安装(关闭)
$mysql_dir/bin/mysqladmin -uroot -p shutdown
oracle
登录
sqlplus usr/pwd@//host:port/sid
查看日志
less /wls/applogs/pafa.log
tail -f /wls/applogs/pafa.log
grep TMJob /wls/applogs/pafa.log
cat esg.properties|grep '内容'
查找文件
查找文件
find / -name "文件名字"
tomcat
启动,在bin目录下
./startup
windows查看端口是否通
telnet 47.95.116.37 8080
查看端口是否被占用
在windows在查看端口是否被占用
1.查看80端口是否被占用
netstat -ano|findstr "80"
2.查看是哪个进程或者程序占用了80端口
tasklist|findstr "2720"
3.杀掉进程,taskkill /f /t /im "进程id或者进程名称"
taskkill /f /t /im "nginx.exe"
在linux查看端口是否被占用
netstat -anp |grep 80(先切换到root用户下)
查看linux上zookeeper是否开启
ps -aux | grep 'zookeeper'
有返回代表开启
查看内存
Top
查看磁盘
df -h
redis
安装(win和linux都有)
https://www.runoob.com/redis/redis-install.html
启动
打开一个 cmd 窗口 使用 cd 命令切换目录到 C:\redis 运行:
redis-server.exe redis.windows.conf
访问
上面那个页面不要关
redis-cli.exe -h 127.0.0.1 -p 6379
cpu占用过高
top查看哪个进程过高
jps -l 或者 ps- ef |grep java |grep -v grep
ps -mp 进程id -o THREAD,tid,time
十进制线程转十六进制
stack 进程 |grep tid (16进制线程id小写) -A60
开机关机
reboot
重启
shutdown -h now
立即重启
安装软件
下载安装包
centos rpm
安装rpm -i jdkxxx.rpm
查找安装 rpm -qa | grep jdk
列表 rpm -qa | more
ubuntu dpkg
安装 dpkg -i xxx.deb
查找安装 dpkg -qa | grep jdk
列表 dpkg -qa | more
软件管家方式
centos yum
搜索 yum search openjdk
安装 yum install openjdk
删除 yum erase opendjk
配置文件 /etc/yum.repos.d/CentOs-Base.repo
ubuntu apt-get
搜索 apt-cache search open
安装 apt-get install openjdk
删除 apt-get purge openjdk
配置文件 /etc/apt/sources.list
下载解压方式
编辑 .bashrc
编辑 /etc/profile
环境变量
export JAVA_HOME=/root/xxx
export PATH=$JAVA_HOME/bin:$PATH
运行/关闭服务
命令行运行
./xxxx
ctrl+c 退出
后台运行
nohup xxxx >out.file 2>&1 &
对进程发出结束的信号
kill pid
强制关闭
kill -9 pid
服务的方式运行
设置开机启动 systemctl enable xxx
启动 systemctl start xxx
关闭 systemctl stop xxx
系统调优
/proc/sys/vm/min_free_kbytes
1. 系统调用
系统调用
Linux内核提供给用户进程进行的调用系统的一些统一接口。
系统调用也能列出来提供哪些接口可以调用,进程有需要的时候就可以去调用。
这是内核和用户进程交互的窗口
glibc 对系统调用的封装
在 glibc 的源代码中,有个文件 syscalls.list,里面列着所有 glibc 的函数对应的系统调用
另外,glibc 还有一个脚本 make-syscall.sh,可以根据上面的配置文件,对于每一个封装好的系统调用,生成一个文件。
框架
常用的系统调用
进程管理
创建进程fork
运行新二进制文件execve
等待子进程结束waitpid
内存管理
调整内存数据段 brk
内存映射mmap
文件管理
打开open
创建 creat
关闭 close
定位 lseek
读取read
写入 write
网络通信
创建套接字 socket
绑定端口 bind
发起连接 connect
接受连接 accept
监听listen
进程通信
消息队列
创建队列 msgget
发送消息 msgsnd
接受消息 msgrcv
共享内存
创建共享内存 shmget
共享内存映射到内存空间 shmat
信号量
抢占信号量sem_wait
释放信号量 sem_post
信号处理
发送信号 kill
信号处理 sigaction
api, posix 和 C库
posix 是IEEE 定的一组标准,Unix完全支持,Linux尽力支持兼容
应用程序 调用 C库 ,C库调用系统调用
C语言代码编译
动态链接库
gcc -shared -fPIC -o libdynamicprocess.so process.o
静态链接库.a 文件
仅仅将一系列对象文件(.o)归档为一个文件,使用命令 ar 创建。
二进制的程序也要有严格的格式,这个格式我们称为ELF(Executeable and Linkable Format,可执行与可链接格式)
2. 内核管理
总纲:Linux内核重要数据结构
OS启动
1. 实模式
2. 保护模式
启动过程
1.BIOS时期约定了启动扇区的位置与大小
2.BootLoader时期主要是通过grub2来启动系统
3.启动过程中有实模式到保护模式的切换。
保护模式就会启动内核
第一项是启用分段
第二项是启动分页
第三项跳转到 kernel.img 开始运行
kernel.img 对应的代码是 startup.S 以及一堆 c 文件
在 Linux 里面有一个工具,叫Grub2,全称 Grand Unified Bootloader Version 2。顾名思义,就是搞系统启动的。
通过 grub2-mkconfig -o /boot/grub2/grub.cfg 来配置系统启动的选项
grub2-install /dev/sda,可以将启动程序安装到相应的位置
内核启动的过程
内核的启动从入口函数 start_kernel() 开始
INIT_TASK
trap_init()
mm_init()
sched_init()
vfs_caches_init()
rest_init()
初始化 1 号进程
用户态祖先进程
1 号进程是 /sbin/init
创建 2 号进程
kthreadd,负责所有内核态的线程的调度和管理,是内核态所有线程运行的祖先。
通过 ps -ef 命令查看当前系统启动的进程,我们会发现有三类进程
操作系统需要区分 哪些是核心资源,哪些是非核心资源
根据权限控制访问资源
x86 提供了分层的权限机制
区域分成了四个 Ring,越往里权限越高,越往外权限越低。
Linux利用了x86提供的分层权限控制机制,
将能够访问关键资源的代码放在 Ring0,我们称为内核态(Kernel Mode);
将普通的程序代码放在 Ring3,我们称为用户态(User Mode)。
将能够访问关键资源的代码放在 Ring0,我们称为内核态(Kernel Mode);
将普通的程序代码放在 Ring3,我们称为用户态(User Mode)。
ps -ef 显示 :用户态的不带中括号,内核态的带中括号。
1. 进程管理
什么是进程
进程是执行时期的程序+相关资源的总和
什么是线程
线程是进程中活跃的对象。
进程树
task list进程列表、也称任务列表,
在内核进程也称为任务task
在内核进程也称为任务task
Linux 内核弄一个链表将进程都管理起来
Linux 内核弄一个链表,将所有的 task_struct 串起来。
task_struct : 进程/线程描述符
进程描述符
slab分配task_struct。
最大存放32768个进程描述符
最大存放32768个进程描述符
可以通过/proc/sys/kernel/pid_max来提高上限
task_struct {
pid_t pid;
pid_t tgid;
struct task_struct *group_leader;
}
pid_t pid;
pid_t tgid;
struct task_struct *group_leader;
}
具体的数据结构
task_struct 我们也称为进程控制块PCB
任务 ID
信号处理
任务状态
TASK_RUNNING 并不是说进程正在运行,而是表示进程在时刻准备运行的状态。当处于这个状态的进程获得时间片的时候,就是在运行中;如果没有获得时间片,就说明它被其他进程抢占了,在等待再次分配时间片。
三种睡眠状态
TASK_INTERRUPTIBLE,可中断的睡眠状态。
TASK_UNINTERRUPTIBLE,不可中断的睡眠状态。
TASK_KILLABLE,可以终止的新睡眠状态
TASK_STOPPED 是在进程接收到 SIGSTOP、SIGTTIN、SIGTSTP 或者 SIGTTOU 信号之后进入该状态。
TASK_TRACED 表示进程被 debugger 等进程监视,进程执行被调试程序所停止。当一个进程被另外的进程所监视,每一个信号都会让进程进入该状态。
一旦一个进程要结束,先进入的是 EXIT_ZOMBIE 状态,但是这个时候它的父进程还没有使用 wait() 等系统调用来获知它的终止信息,此时进程就成了僵尸进程。
EXIT_DEAD 是进程的最终状态。
现代操作系统提供了两种虚拟机制
虚拟处理器
进程调度程序
cpu资源怎么划分呢,由内核进程的进程调度程序说了算,进程调度程序是一个内核进程
CPU管理
调度策略
实时进程
需要尽快执行返回结果
SCHED_FIFO、SCHED_RR、SCHED_DEADLINE 是实时进程的调度策略。
SCHED_FIFO就是交了相同钱的,先来先服务,但是有的加钱多,可以分配更高的优先级,也就是说,高优先级的进程可以抢占低优先级的进程,而相同优先级的进程,我们遵循先来先得。
交了相同钱的,轮换着来,这就是SCHED_RR 轮流调度算法,采用时间片,相同优先级的任务当用完时间片会被放到队列尾部,以保证公平性,而高优先级的任务也是可以抢占低优先级的任务。
SCHED_DEADLINE,是按照任务的 deadline 进行调度的。当产生一个调度点的时候,DL 调度器总是选择其 deadline 距离当前时间点最近的那个任务,并调度它执行。
普通进程
普通进程的调度策略有,SCHED_NORMAL、SCHED_BATCH、SCHED_IDLE。
SCHED_NORMAL 是普通的进程,就相当于咱们公司接的普通项目。
SCHED_BATCH 是后台进程,几乎不需要和前端进行交互。这有点像公司在接项目同时,开发一些可以复用的模块,作为公司的技术积累,从而使得在之后接新项目的时候,能够减少工作量。这类项目可以默默执行,不要影响需要交互的进程,可以降低他的优先级。
SCHED_IDLE 是特别空闲的时候才跑的进程,相当于咱们学习训练类的项目,比如咱们公司很长时间没有接到外在项目了,可以弄几个这样的项目练练手。
Linux操作用的是CFS调度算法:公平调度算法
优先级/nice值
表示分配的时间片的比例
更小的nice值有更高的时间片优先级
更高的nice值有更低的时间片值
虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD/ 权重
目标延时
deadline算法中的一种
为了防止饥饿现象
时间片控制
最小粒度
CFS算法为每个进程获得的时间片的最小粒度默认为1ms,可以配置
时钟中断管理和度量时间
虚拟内存
在操作系统中,每个进程都有自己的内存,互相之间不干扰,有独立的进程内存空间。
子主题
创建进程
创建进程的系统调用叫fork。
在 Linux 里,要创建一个新的进程,需要一个老的进程调用 fork 来实现,其中老的进程叫作父进程(Parent Process),新的进程叫作子进程(Child Process)。
当父进程调用 fork 创建进程的时候,子进程将各个子系统为父进程创建的数据结构也全部拷贝了一份,甚至连程序代码也是拷贝过来的。
对于 fork 系统调用的返回值,如果当前进程是子进程,就返回 0;如果当前进程是父进程,就返回子进程的进程号。这样首先在返回值这里就有了一个区分,然后通过 if-else 语句判断,如果是父进程,还接着做原来应该做的事情;如果是子进程,需要请求另一个系统调用execve来执行另一个程序,这个时候,子进程和父进程就彻底分道扬镳了,也即产生了一个分支(fork)了。
有个系统调用waitpid,父进程可以调用它,将子进程的进程号作为参数传给它,等带子进程运行完成。
#include <sys/types.h>
pid_t child_pid;
child_pid = fork ();
child_pid = fork ();
fork 的第一件大事:复制结构
fork 的第二件大事:唤醒新进程
进程处理信号
在执行一个程序的时候,在键盘输入“CTRL+C”,这就是中断的信号,正在执行的命令就会中止退出;
用户进程通过kill函数,将一个用户信号发送给另一个进程。
SIGKILL(用于终止一个进程的信号)
SIGSTOP(用于中止一个进程的信号)
线程系统调用
#include <pthread.h>
pthread_create(&threads[t], &thread_attr, downloadfile, (void *)files[t]);
互斥量
pthread_mutex_lock(&g_money_lock);
在操作系统中,每个进程都有自己的内存,互相之间不干扰,有独立的进程内存空间。
子主题
在操作系统中,每个进程都有自己的内存,互相之间不干扰,有独立的进程内存空间。
子主题
2. 中断和中断处理(驱动开发者关注比较多)
概念
中断其实是一个电信号,由硬件设备产生,发送给cpu,cpu检测到这个信号,会中断自己目前的工作来处理这个中断
中断响应程序称为中断处理程序/中断服务历程(interrupt service runtime , ISR)
一般只说中断就是硬中断
响应中断的处理一般分为上半部和下半部
上半部
就是我们说的硬中断
需要处理时间特别快
实际开发
注册中断处理程序
释放中断处理程序
中断上下文
有一个队列,实现中断处理机制
中断控制
可以屏蔽中断
可以激活中断
下半部
上半部时间越短越好
下半步有三种处理方式
软中断
softirqs
网络适配器用它
tasklet
在软中断的基础上封装了一下
一般情况使用它就好
bh及工作队列
bh已经被淘汰
2.5之前淘汰,其它的都是2.3之后引入
任务队列是替换机制
实现上使用了位图,上半部修改位图的一个bit,下半部读到bit修改去对应位置执行下半部的操作
ksoftirqd内核线程处理软中断等下半部操作
每个处理器都有一组辅助处理的ksoftirqd,比如ksoftirqd/n
3. 内存管理
内存空间 会存放 xx 部分数据
代码段(Code Segment)
进程的内存空间来讲,放程序代码的这部分,我们称为代码段(Code Segment)。
数据段(Data Segment)
放进程运行中产生数据的这部分
堆(Heap)
动态分配的,会较长时间保存,指明才销毁的
mmap
当分配的内存数量比较大的时候,使用 mmap,会重新划分一块区域
brk
当分配的内存数量比较小的时候,使用 brk,会和原来的堆的数据连在一起
虚拟内存空间要一分为二,一部分是用户态地址空间,一部分是内核态地址空间,那这两部分的分界线在哪里呢?这就要 task_size 来定义。
虚拟内存空间
虚拟内存空间的管理,每个进程看到的是独立的、互不干扰的虚拟地址空间
页: 地址空间
内存描述符
vm_area_struct
这里面一个是单链表,用于将这些区域串起来。另外还有一个红黑树。又是这个数据结构,在进程调度的时候我们用的也是红黑树。它的好处就是查找和修改都很快。这里用红黑树,就是为了快速查找一个内存区域,并在需要改变的时候,能够快速修改。
代码段、全局变量、BSS
函数栈
堆
内存映射区
匿名页,和虚拟地址空间进行关联
内存映射,不但和虚拟地址空间关联,还和文件管理关联
创建地址区间
内核
do_mmap()
用户态
mmap()
底层调的是mmap2()
删除地址区间
内核
do_munmap()
用户态
munmap()
用户态可以通过 malloc 函数分配内存
malloc小于128k的内存,使用brk分配内存,节约内存
malloc 在分配比较大的内存的时候,底层调用的是 mmap,当然也可以直接通过 mmap 做内存映射,在内核里面也有相应的函数。
缺页异常,内存不足
页高速缓存和页回写
临时局部原理:数据一旦被访问了,就很有可能在短期内再次被访问到
根据临时局部原理,Linux设计了页高速缓存
Linux写缓存的策略
回写
进程写文件并不会直接写到文件中,而是写到缓存中。再标记这一页是“脏”页
然后有另外一个进程周期性地将脏页链表中的数据写回磁盘,达到内存磁盘最终一致性。因此Linux有断电丢失文件的风险
然后有另外一个进程周期性地将脏页链表中的数据写回磁盘,达到内存磁盘最终一致性。因此Linux有断电丢失文件的风险
缓存回收
1. LRU
2. LRU/n
Linux回收动作是选择干净的页进行数据替换。
回写线程
第一代
bdflush、kupdated和pdflush
第二代
2.6内核之后
flusher
第三代
3.10内核
kdmflusher
回写的内核设置
dirty_backgroud_ratio
dirty_expire_interval
dirty_ratio
dirty_writeback_interval
laptop_mode
是否开启膝盖模式
物理内存的管理
物理内存的管理,物理内存地址只有内存管理模块能够使用
页
mm_struct
内核的代码、全局变量、BSS
内核数据结构例如 task_struct
内核栈
内核中动态分配的内存
区
内核对页的组织
页表:内存映射
内存映射,需要将虚拟内存和物理内存映射、关联起来
32位系统3级页表项
64位系统4级页表项
内存的换入和换出涉及 swap 分区
内核线程kswapd负责。这个内核线程,在系统初始化的时候就被创建。这样它会进入一个无限循环,直到系统停止。
syscall
获取给定的地址是哪一个内存区域
find_vma()
4. 文件系统管理
Linux 里有一个特点,那就是一切皆文件
VFS: 虚拟文件系统
虚拟文件系统相当于图书馆的查书系统,文件相当于书
超级块对象
索引节点对象
inode
文件的元数据部分,例如名字、权限
链接(Link)
创建
ln [参数][源文件或目录][目标文件或目录]
ln -s 创建的是软链接,不带 -s 创建的是硬链接。
硬链接(Hard Link)
硬链接与原始文件共用一个 inode 的,但是 inode 是不跨文件系统的,每个文件系统都有自己的 inode 列表,因而硬链接是没有办法跨文件系统的。
软链接(Symbolic Link)
软链接相当于重新创建了一个文件。这个文件也有独立的 inode,只不过打开这个文件看里面内容的时候,内容指向另外的一个文件。这就很灵活了。我们可以跨文件系统,甚至目标文件被删除了,链接文件还是在的,只不过指向的文件找不到了而已。
挂载文件
目录项对象:dentry
文件对象:file
常用syscall
目录
opendir 函数打开一个目录名所对应的 DIR 目录流。并返回指向 DIR 目录流的指针。流定位在 DIR 目录流的第一个条目。
readdir 函数从 DIR 目录流中读取一个项目,返回的是一个指针,指向 dirent 结构体,且流的自动指向下一个目录条目。如果已经到流的最后一个条目,则返回 NULL。
closedir() 关闭参数 dir 所指的目录流。
文件
mount 系统调用用于挂载文件系统;
open 系统调用用于打开或者创建文件,创建要在 flags 中设置 O_CREAT,对于读写要设置 flags 为 O_RDWR;
read 系统调用用于读取文件内容;
write 系统调用用于写入文件内容。
文件系统图
5. 输入输出设备管理
块设备整体视图
块I/O 调度层
磁盘
Linus电梯调度算法
算法概述
通过合并IO调度请求,并且根据指针给IO调度请求排序,维护一个请求队列,另外个进程读这个队列头去磁盘做读写处理就好,这样对机械硬盘有磁头的硬盘非常友好。最大限度地提高IO调度吞吐量
实现
排序
合并
一般已经不使用了
能够达到块设备IO的最大吞吐量,但是也会造成饥饿效应
比如坐电梯的时候目前电梯在一楼,但是每一层都停一下,然后你的在最顶层,那么最顶层的用户是不是需要等很久呢?是的
deadline 调度算法
算法概述
在Linux电梯算法上做出优化:维护多3个队列
读队列
冗余一个读请求在这个队列,发现头部请求超时的时候,放入派发队列
写队列
冗余一个写请求在这个队列,发现头部请求超时的时候,放入派发队列
排序队列
这个队列和电梯算法的队列一模一样
一般情况取这个头部放入派发队列
派发队列
真正根据队列头尾去读磁盘的IO调度队列
实现
4个队列
合并
排序
冗余多一分数据
在MySQL,RocketMQ中建议使用
as 调度算法
算法概述
在deadline上作出的优化:as=deadline + 预测启发
让读队列/写队列的请求停留一段时间(6ms),让其它新进来的请求趁机插队,在deadline的基础上减少几次IO
这也是Linux默认的调度算法
对服务器非常友好
cfq 完全公平排队调度算法
算法概述
每个进程的IO请求都创建一个队列,然后队列是根据发起IO请求的先后顺序排序的,然后cfq调度程序轮询调度每个队列的头4个请求(默认值是4,可以配置)
适合桌面系统
noop(空转) 算法
算法概述
电梯算法去掉排序,只有合并
对U盘,闪卡比较好
驱动算法比较适合
键盘设备
块IO操作的结构体 bio
bio的目的是表示现场执行的IO操作
VFS 和 块IO的关系
6. 定时器和时间管理
这个时间片切割,会产生硬中断
周期性地产生事件
x86架构中,系统定时器频率默认值是100HZ,就是没10ms产生一次时钟中断
Linux的ServCon函数设置10ms执行一次的原因就是在这里
x86架构支持改成其它配置,比如1ms
高HZ的优势
对poll()和epoll()这些定期执行的系统操作更加高精度黄执行
时间精度更高
系统资源消耗更准,提高cpu抢占的准确度
高HZ的劣势
中断多了,系统负担页重了,要花跟多资源支持中断,处理其它任务的时间少了
jiffies
全局变量jiffies用来记录来自系统启动以来的节拍总数
0 条评论
下一页