【5.linux操作系统】-内核进程/线程/系统调用/调度

linux调度

本质:虚拟处理器,虚拟内存
分类:抢占,非抢占。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

内核系统调用 帮助进程通信,访问硬件,申请资源

软中断 0x80=》system_call eaax寄存器中断号 参数:寄存器中,若多于6个,用单独寄存器存放指向所有参数在用户空间地址的指针 返回值:eax寄存器

进程状态

  • 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

进程内存管理

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

虚拟内存

栈  参数,env 栈指针 sp寄存器
堆                                                  
未初始化                                            
初始化
文本

页表(空页未使用虚拟空间无页表)
RAM(只有程序的部分页 ) 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
daemon过程:
fork
子进程setsid
若已打开过终端再fork子进程不会成为会话组长,不会重新打开终端
清除umask,修改工作目录,关闭父进程fd
信号处理
syslog

问题

1.进程和线程的区别(进程独立数据地址空间),父子进程共享哪些内容,线程独占哪些内容;进程创建和线程创建初始化的资源;
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

2.进程调度方式,进程什么情况会休眠;
抢占,调度器: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),内核进程阻塞,显示调用会调用

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

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

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

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

你可能感兴趣的:(c++)