linux内核进程线程系统调用会话调度

44次阅读

共计 3777 个字符,预计需要花费 10 分钟才能阅读完成。

虚拟处理器,虚拟内存
抢占,非抢占。IO/ 处理器型
调度
优先级

  nice 与其他系统不同是时间片比例,-20~19(越小越高)实时优先级 0-99 越大越高  高于普通的 nice

调度器
1.CFS
时间记账:task_struct 的 se vruntime(这个时间是经过了所有可运行进程总数的标准化,理想下相同优先级有相同 vruntime)
选择最小 vruntime 红黑树 可运行队列,最左侧节点缓存
2. 实时调度 FIFO,RR,IDLE
FIFO:一直运行直到阻塞 / 更高优先级的抢占
RR:有时间片,耗尽后,同优先级轮流
IDLE 比 nice19 优先级还低

cpu 高速缓冲器(1 行 32-128 字节)
getruasge
getrlimit

进程状态
runing(sleep 也是 run)
可中断睡眠(系统调用等软中断)
不可中断(硬中断)忽略信号
等待队列简单链表 wait_queue_head_t=》队列相关事件发生时 wake_up=>try_to_wake_up 加入红黑树 设置 need_resched
进程上下文切换:switch_mm 把虚拟内存从上一个进程映射切换到新进程中。switch_to 负责从上一个进程的处理器状态切换到新进程的处理状态,保存 / 恢复栈信息 / 寄存器信息
用户抢占(用户间切换是安全的):从系统调用过或中断返回用户空间,need_resched 设置掉 schedule()
内核抢占(抢占内核进程),中断返回内核(内核进程 thread_info 的 preempt_count=0&&need_resched),内核进程阻塞,显示调用会调用
traced stopped

内核系统调用 帮助进程通信,访问硬件,申请资源
软中断 0x80=》system_call eaax 寄存器中断号 参数:寄存器中,若多于 6 个,用单独寄存器存放指向所有参数在用户空间地址的指针 返回值:eax 寄存器

sched.h task_struct (slab 分配该结构) 内核栈底,所有 task_struct 已双向链表组织在一起,task list
current 宏

虚拟内存 页表 RAM
栈 参数,env 栈指针 sp 寄存器 空页未使用虚拟空间无页表 只有程序的部分页
堆 swap
未初始化 磁盘
初始化
文本

进程操作
fork 复制父进程页表 创建 pid 父写也会复制,立即 exec 省去复制过程(都是 clone=>do_fork)
文件描述符副本相互影响
代码段只读,共享,页表项指向父进程相同 RAM 页
其他段写时复制
fork 后哪个先更好?子先在 exec 避免了页表的拷贝
父先 cpu 中活跃提高性能

vfork 不拷贝页表(不推荐使用)
内核线程 mm 为 Null
exit 删除定时器,ipc 信号,文件,向父进程发信号,剩余内核栈,thread_info,task_struct
调用 atexit/on_exit 注册函数
刷 stddio 缓冲区
_exit 关闭 fd。文件锁 /sem_close/mq_close, 取消 mmap,mlock 等
print fork exit
print 是 stdio 函数有缓冲区,fork 时在用户空间内存上复制 exit 刷新。会打印两份 print 内容(若 write 只有一份)
setbuf.print 前 fflush。一个进程用 exit 其他_exit

wait 挂起直到子进程退出
waitpid 可指定 pid 非阻塞
wait3 wait4 统计 rusage
zomble
SIGHUP 子进程终止发给父进程 =》循环 waitpid
execve 重新创建栈 数据段,

线程 pthread linuxthread(千线程)/nptl(10 万)比进程快 10 倍
独有:tid,信号 mask, 栈,浮点型环境,优先级,cpu 亲和力等
线程同步:互斥量 / 条件变量
1. 静态 phreaad_mutex_initializer lock try_lock 不阻塞
性能:文件锁 / 信号量 锁定和解锁总需要发起系统调用,互斥量在内存中执行对所有线程可见,只有发生锁征用时 futext()系统调用
避免死锁:按顺序 lock->try_lock 失败释放所有
动态 pthread_mutext_init()
2. 条件变量
pthread_cond_initilizer signal breadcast wait
这个变量也要加互斥量 lock wait(unlock xxx lock) unlock
线程安全:互斥量
thread_once
线程特有数据 pthread_key_create pthread_setspecific 一个全局数组 为每个线程设置与 key 对应元素
线程局部存储 __thread 每个线程有一个拷贝
cancel 延时取消,到取消点(可作为取消点的函数比如 print,sleep 等)取消点前可以调用清理函数。异步取消任何时候取消不能完好清理
信号 动作 / 处置是进程层面的,真对线程:pthread_kill 等
多线程收到一个信号,已创建 handler 选一条线程接收处理
exec 任意线程调用 程序被替换,其他线程消失,线程 ID 不定
fork 子进程复制这一线程,包括互斥量等
exit 任何线程调用,全消失
线程与调度实体,采取 1:1 实现 每个线程为一个 KSE,都要切到内核 (M:1 调度等由用户线程处理)

会话
会话首进程 pid ppid pgid 组 sid 会话
进程组 首 pid
非首进程 setsid 会创建一个新会话
会话的孤儿进程组,停止但未终止,不会被回收(发 HUP->CONT 解决)
daemon
cron sshd httpd inetdd
fork
子进程 setsid
若已打开过终端再 fork 子进程不会成为会话组长,不会重新打开终端
清除 umask,修改工作目录,关闭父进程 fd
信号处理
syslog

进程和线程的区别 (进程独立数据地址空间),父子进程共享哪些内容,线程独占哪些内容;进程创建和线程创建初始化的资源;
fork 区别 pid,ppid, 某些统计量,某些资源比如挂起的信号。拷贝或共享打开的文件,文件系统信息,信号处理函数,进程地址空间,命名空间。
具体:创建内核栈,thread_info,task_struct。初始化。分配 pid。共享 / 拷贝进程地址空间页表等。线程前 6 个也差不多。共享的更多。
但最终两个进程相同程序文本段,共享文件描述符。各自不同栈,数据段,堆等 P505
线程:共享的地址空间,文件资源和处理,文件描述符,nice 值等 clone(clone_vm|clone_fs|clonne_files|clone_sighand,0)
独有:tid,信号 mask, 线程独有数据,栈,浮点型环境,cpu 亲和力等 p511

进程调度方式,进程什么情况会休眠;
抢占,调度器:CFS/ 实时 FIFO,RR 等。
等待队列简单链表 wait_queue_head_t=》队列相关事件发生时 wake_up=>try_to_wake_up 加入红黑树 设置 need_resched
进程上下文切换:switch_mm 把虚拟内存从上一个进程映射切换到新进程中。switch_to 负责从上一个进程的处理器状态切换到新进程的处理状态,保存 / 恢复栈信息 / 寄存器信息
用户抢占(用户间切换是安全的):从系统吊用过或中断返回用户空间,need_resched 设置掉 schedule()
内核抢占(抢占内核进程),中断返回内核(内核进程 thread_info 的 preempt_count=0&&need_resched),内核进程阻塞,显示调用会调用

可中断睡眠(某些阻塞的系统调用 / 软中断,比如等待终端输入,等待空管道 / 信号量),不可中断(硬中断)忽略信号

系统调用如何传递参数和获取返回结果;
软中断 0x80=》system_call eaax 寄存器中断号 参数:寄存器中,若多于 6 个,用单独寄存器存放指向所有参数在用户空间地址的指针 返回值:eax 寄存器

内存布局,内核地址和进程地址;
系统打开最多文件个数,创建最多进程数,会被那些因素制约;
句柄地址 (稳定)→记载着→对象在内存中的地址(不稳定)
其中 open files 表示的是单个进程最多允许打开的文件句柄数(soket 连接数也算在内),默认值是 1024。对于一般的程序来说,这个值是足够的
限制?打开句柄 =》系统打开表 =》文件 /ram 句柄对应地址的查询太慢?
进程数:虚拟内存大小。内核 task_struct 1.7k(32 位),thread_info(比较少)。pid int 类型的兼容 可改 几万

内核空间和用户空间,内存怎么跟着进程切换;
进程上下文:进程的上下文信息包括,指向可执行文件的指针, 栈, 内存 (数据段和堆), 进程状态, 控制信息(信号等),寄存器组(栈指针, 指令计数器),硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)等等
进程上下文切换:switch_mm 把虚拟内存从上一个进程映射切换到新进程中(进程的 mm_struct 的地址映射,加载页表, 刷出地址转换后备缓冲器 (部分或者全部), 向内存管理单元(MMU) 提供新的信息)。switch_to 负责从上一个进程的处理器状态切换到新进程的处理状态,保存 / 恢复栈信息 / 寄存器信息
(https://blog.csdn.net/gatieme…)
中断和进程上下文的关系
当程序系统调用到内核空间,内核代表进程执行,并处于进程上个下文中,current 宏是有效的,除非高优先级抢占否则退出还恢复用户空间继续执行。中断上下文,内核执行中断处理程序。不会有进程去干扰

正文完
 0