重定位
进程的重定位指将程序加载到内存中不同的位置执行,在进程换出换入过程中将会发生。通过更新程序中使用的相对地址。
进程的创建——fork()
进程树,在自己的节点下创建进程节点。
使用fork,创建的子进程是父进程副本吗,继承当前数据,代码段,pc,文件描述符等,但是堆栈是各自的,两个进程之后独立执行。fork子进程中返回的是0,父进程返回进程的PID。
申请PCB——初始化PCB——分配资源(从父进程继承或者共享)——加入就绪队列——返回PCB
执行方法有两种:
- 父进程等待子进程执行完毕。
- 两者同时执行。
父进程终止,子进程在节点树上没有父节点,也会终止。
子进程exit(),操作系统回收空间,并且返回父进程信号。
进程间通信
- 共享内存,生产者——消费者模型
- 网络
线程和进程调度
在Linux中,操作系统支持进程和线程的调度。在Linux中,线程被视为与进程相同的调度实体,因为Linux将线程实现为轻量级进程(LWP,Lightweight Process)。linux下操作系统调度的是进程和lwp(由进程内部的线程映射过来的)。
线程共享进程的内存空间,可以互相通信
线程的创建
在Linux中,操作系统支持进程和线程的调度。在Linux中,线程被视为与进程相同的调度实体,因为Linux将线程实现为轻量级进程(LWP,Lightweight Process)。## 指令周期包含多个CPU周期
一个指令周期包括:取指令——分析指令——取地址——运算——放回
多线程下的临界区问题
共享资源变量,抢占的对称多处理器。
基于硬件的原子操作可以实现锁。TestAndSet(),TestAndSet(),通过硬件指令实现。
通过TAS或SWAP实现的自旋锁
while(TAS(&lock));
信号量解决忙等待
二进制信号量:互斥锁
常量信号量:资源数
typedef struct{int value;PCB* queue;
}semaphore;
wait(semaphore* s){s->value--;if(s->value<0{将这个线程添加到queue;block();让权等待}
}
signal(semaphore* s){s->vlaue++;if(vlaue<=0){队首出队;wakeup(p);唤醒队首}
}
block()将线程阻塞和wackup()唤醒线程,是通过操作系统来实现的。
Peterson算法
举手礼让策略
bool flag[2]={false};
int turn=0;P0{while(true){flag[0]=true;//举手turn=1;//礼让while(flag[1]&&turn==1);//礼让flag[0]=flase;}
}