进程
- 进程:是动态正在运行程序系统分配资源的最小单位。 系统最多只能同时运行与处理器数相同的任务数
- SMP :对称多处理 处理器通过调度算法执行任务
- 时间片: 根据不同进程分配一个合适执行时间片(每个进程的时间片不同).由于时间片的时间太短人几乎感觉不到时间差
进程状态
- 进程准备运行或运行(running 进程进入到准备运行队列中)
- 2.堵塞(block)
- a.等待:可中断堵塞,可以接收硬件响应或系统信 号,唤醒之后可以进入到准备运行队列
- b.睡眠:不中终端堵塞,可以接收硬件响应但不能接收系统信号,睡眠状态不能直接进入到准备运行队列
- 停止状态(stop)
- .僵死状态():进程结束释放部分资源,但在父进程的子进程链表中仍然存在子进程节点
进程地址空间结构
- 代码段 存储代码和字面常量,属于只读区域不能修改
- 数据段 初始化的全局和静态变量
- BSS段 未初始化的全局和静态变量
- 堆 用户自己分配释放
- 共享区(文件内存映射区)
- 栈 函数参数值,局部变量,返回地址等 高地址–>低地址
- 命令行参数和环境变量
- 内核空间 在32 位系统中(进程地址空间大小为4G 用户空间3G(0-3) 内核空间1G(3-4))
进程编程
fork
-
__pid_t fork(); 从fork函数成功返回之后,就存在两个进程, 调用clone函数 完全复制父进程虚拟地址空间,依据COW 写时复制
返回值 pid=0:子进程中获取值
pid>0:父进程中获取值
pid==-1:失败(内存不够)fork成功返回 父子进程执行顺序不定,/proc/sys/kernel/sched_child_runs_first 内核设置子进程线运行配置文件 (0 父进程先执行 1 子进程先执行)
-
写时复制 当父或子进程修改值之前复制到另外一个进程.
-
子进程复制父进程:(复制内容)
数据段 栈 打开文件描述符 资源限制 实际用户id 有效用户id 实际用户组id 有效用户id 进程组id -
子进程不复制父进程内容:
代码段共用 资源当前使用值请0 进程id CPU使用时间 未抵达的信号 内存锁 记录锁 记录锁 定时器(alarm timer) 信号量
子进程id是通过进程id hash表中从小到大分配一个未使用的值. -
子进程先执行能在一定程度上避免写时复制 提高效率和内存利用率
chen@ubuntu:~/work$ cat /proc/sys/kernel/sched_child_runs_first 0 chen@ubuntu:~/work$ 系统配置父进程先执行 int main(int argc,const char* argv[]) { printf("parent process is running\n"); printf("parent pid=%d\n",getpid());//获取正在被执行进程ID值 pid_t pid=fork(); if(pid==-1) { perror("fork error\n"); } if(pid==0) { //子进程执行语句 printf("child pid=%d\n",getpid()); } if(pid>0) { //父进程执行语句 printf("pid=%d\n",pid); printf("parent pid=%d\n",getpid()); } //父子进程执行语句 printf("running end\n"); return 0; } 运行结果 parent process is running parent pid=3815 pid=3816 parent pid=3815 parent running end child pid=3816 parent running end 修改配置文件 为1 运行结果 parent process is running parent pid=3848 pid=3849 parent pid=3848 parent running end child pid=3849 parent running endvfork
-
父子进程共用进程地址空间
-
父进程堵塞,直到子进程结束,父进程唤醒
-
进程间值的修改会有影响
-
子进程 必须调用exit函数否则出现段错误
int main(int argc, char const *argv[]) { int data=300; printf("child parent process id=%d:\n",getppid()); pid_t pid=vfork(); if(pid==0) { printf("child process running:\n"); data=600; printf("child parent process id=%d:\n",getppid()); printf("child process data=%d:\n",data); // while(1) // { // } printf("child process data=%d:\n",data); printf("child parent process id=%d:\n",getppid()); //exit(0); / } /// //子进程公用父进程栈空间,子进程不调用exit函数切换导致子进程运行结束释放栈,父进程开始运行,访问一个不存在栈空间 if(pid>0) { printf("------------parent process running:\n"); printf("child process data=%d:\n",data); } return 0; }
孤儿进程
子进程未结束,父进程结束。
僵尸进程
- 概念:父进程未调用wait/waitpid,未收到子进程结束信号
- 如何避免
- 进程调用wait/waitpid
- 在信号处理函数中调用wait/waitpid
- 父进程忽略SIGCHLD,让内核处理
-
进程间通信
进程资源中的名词概念
-
临界资源 一个时刻只能被一个进程修改的资源
-
临界区 修改访问临街资源的语句
-
进程同步 让多个进程有序访问临界资源
-
进程互斥 同一时刻只能有一个进程访问临界资源,其他进程堵塞,进程访问资源是无序的
-
进程并发 (单核)多个进程合作完成某个操作,但是一个时刻只能有一个进程执行
-
进程并行 (多核)一个时刻有多个进程同时执行
-
**进程异步 ** 一个进程未结束另一个进程可以执行,回调函数实现进程异步操作
-
锁 是原子类型执行原子操作的变量
-
死锁:多个进程构成资源的相互等待.
- 发生死锁的原因:
1.系统资源不足
2.进程执行顺序不合适
3.资源分配不均 - 发生死锁的必要性:
1.互斥性
2.坚持性(占用资源之后,坚持占有)
3.不可剥夺性(资源不能被抢占)
4.循环等待性 - 如何避免死锁发生:
1.资源均匀分配
2.合理安排进程执行顺序
3.合理阻止循环等待
4.可以实现资源抢断
- 发生死锁的原因:
-
进程同步互斥的方式
- 互斥锁
- 大内核锁
- 读写锁
- 自旋锁 内核中的一种锁,当资源已经被锁住,进程不堵塞,继续运行,消耗CPU,等待解锁,只能适合较短的操作
- 缺点:消耗CPU, 容易出现死锁
- 优点:避免进程执行数据换入换出(CPU寄存器的数据域恢复
- 信号
- 信号量 内核中的一种锁,是通过 P,V 操作一个资源数记录变量,如果是P操作消耗资源资源记录数减一,当资源记录数<=0时,请求消耗资源的进程堵塞,如果是V操作,资源记录数加1 -
**中断 ** 中断电路发送电平信号给中断控制器,中断控制器通知CPU(控制器)停止执行当前的指令
- 中断服务函数(程序)的特点:
1.快速执行结束,不能堵塞,睡眠.
2.没有返回类型
3.interrupt 修饰
4.没有参数
5.不能有输出
6.中断函数不能使用浮点数 - 中断函数作用(用途):
1.主要解决外围的响应速度比不上内核(处理器 CPU)的执行速度.提高CPU的利用率
2.快速执行终端的服务程序,随时可能执行中断程序,解决了(polling)轮询执行弊端
3.中断的保护(保存当前数据CPU寄存器值,栈)与终端的恢复(影响效率进程上下文的换入换出)
- 中断服务函数(程序)的特点:
-
原子类型:内核定义(锁级别的变量数据类型)类型(atomic_t)对原子类型的变量必须进行原子性操作(原子类型与硬件设备相关)、
-
原子型操作:执行语句不可中断的操作
进程间通信方式
-
管道;
-
匿名管道 (pipe) :在内核划分一块内存,具有文件inode节点值,又不是一个物理文件,可以用文件操作方式(文件描述符)操作管道.
-
匿名管道特点:
1.只能实现具有亲属关系的进程(fork创建)
2.传输数据是无格式,字节流.传输数据量不能太大.
3.分为读端/写端
4.半双工工作模式(单向传递)
5.如果写端未关闭(存在写进程),读一个空的管道,读进程堵塞如果写端已关闭(写进程结束),读一个空的管道,读进程立即结束(读取函数返回值为0)
6.如果读端未关闭(存在读进程),写一个满管道,写进程堵塞如果读端关闭(读进程结束),写进程继续写数据,内核发送一个SIGPIPE信号,此信号默认动作结束写进程
7.读取管道数据后,数据被清空 -
匿名管道实现双向通信
/* 用匿名管道实现进程的双向通信 创建的管道为半双工工作模式 创建两个管道实现双向通信 */ int main(int argc, char const *argv[]) { int pipe_fd[2],pipe_fd1[2]; pipe(pipe_fd); pipe(pipe_fd1); pid_t pid=fork(); if(pid==
-
-
最低0.47元/天 解锁文章
353

被折叠的 条评论
为什么被折叠?



