图片版在这:https://www.cnblogs.com/pdev/p/10576835.html
上完5103其实就该总结一下的......还是懒 (呵
1. 进程栈
函数调用时,函数参数、返回地址、环境、函数内非static的局部变量存入栈。(栈空间是专门留给函数用的)
程序内所有malloc/new出来的空间、全局变量、所有的static变量存入堆。
(Ref:https://www.cnblogs.com/pdev/p/11289870.html)
堆是从低地址向高地址增长的,栈相反。参考下图
2. 内核态和用户态、system call
User programs are typically executed in user mode. In user mode, program cannot control devices or access memory address directly. All privileged operations should be executed by using system call. A user program executes in the USER mode and it is given limited privileges. Region of memory it can access is restricted. It cannot execute certain instructions such as HALT or setting or changing timers. It cannot directly access any I/O devices or network ports. The primary reason is to protect the system and other user processes and the file system from a misbehaving program.
Kernel code is trusted to be safe and correct. This code is executed in Privileged/Supervisor Mode. It can execute any operation (i.e. instruction). A user process executes the kernel code by making a system call.
System Call的全过程:
System Call和普通函数调用(procedure call)的对比:
system call:
1. Push all parameters into user mode stack
2. put the code of system call into CPU register (in other words, call this procedure)
3. execute a trap instruction, so it will start executing in kernel mode at a fixed address.
4. kernel code will be dispatched to a system-call handler, and the system-call handler runs in kernel mode.
5. After the kernel code finished, switch back to user mode and return to the instruction following TRAP in system call library procedure.
6. After the system call finished, return to user program.
7. The user program will clean up the parameters of system call in the stack, and user program continues.
procedure call:
1. Push all parameters into user mode stack
2. put the code of procedure call into CPU register (in other words, call this procedure)
3. execute the procedure in user mode
4. After procedure call finished, return to user program.
5. The user program will clean up the parameters of system call in the stack, and user program continues.
The procedure call does not need to switch betweenuser mode and kernel mode, so it will save time
Interrupts & exceptions & System calls & traps
Interrupts source: External devices (eg: finish I/O operation on hard disk). Goal: CPU could work in parallel with devices
Exceptions source: Errors in CPU when executing instructions. Goal: Handle internal errors in CPU (eg: divided by zero)
System calls source: Program manually call system call functions provided by operating system. Goal: Execute features which needs OS support (eg: I/O)
Traps source: TRAP instruction in program. Goal: Transfer from user mode into kernel mode
fork()函数
1.Only the thread who called fork() will be forked to new child process. So the child process only have 1 thread.
2.The child process will copy all the memory data from its parent process. Then they will run as independent processes. In modern operating systems, they will do
copy-on-write in fork(), which means both parents and child will receive a read-only copy of the parent's data space, instead of copying the whole data in the first
place. The copy will actually occur when one of them want to modify some data.
3.Based on (2), mutex variables will be copied into child process. Suppose we added locked a mutex before fork(). After fork(), the mutex in the child process will
remain locked, and there will be only one thread in the child process, which means this mutex in child process will never be unlocked(and this is called deadlock). Even if we unlocked mutex in parent process, the one in child process will not be modified.
4.Based on (2), File descriptors will be copied into child process. So they will have the same file pointer, which will point to the same file table. Thus the file status
opened in both processors(include their filename, current file offset) are shared.
clone()函数
Linux provides a more powerful function than fork for creating a new process or thread.
• It can be used to create a new process as in case of fork.
• It can also be used to create a new thread in the address space of the calling process.
进程的上下文切换(略)
进程和线程的区别
A process represents one single sequential activity. – one execution context (Program counter and stack)
A thread represents one activity -- one context and stack per thread.
All Threads of one process can share resources such as memory, open files, and communication channels.
- 进程是资源分配的独立单位
- 线程是资源调度的独立单位
All threads in a process share the following items:
– Address space
– Global variables
– Open files / resources
– Child processes
– Signals and signal handlers
– Accounting Information
Thread specific items:
– Program counter and registers (execution context)
– Stack
– Execution state (ready, waiting, running)
进程之间私有和共享的资源
- 私有:地址空间、堆、全局变量、栈、寄存器
- 共享:代码段,公共数据,进程目录,进程 ID
线程之间私有和共享的资源
- 私有:线程栈,寄存器,程序寄存器
- 共享:堆,地址空间,全局变量,静态变量
协程
进程是资源分配的最小单位,线程是CPU调度的最小单位。而协程可以理解为同一个线程通过上下文切换来“超线程”,并发执行两个工作。比起线程,协程更加轻量,而且多个协程访问同一资源不需要加锁(因为本质上还是在同一个线程内)。
协程的详细定义可以参考这里。另外go语言对协程有很好的支持。
进程/线程之间的通信方式总结
进程之间的通信方式以及优缺点 管道(PIPE) 有名管道:一种半双工的通信方式,它允许无亲缘关系进程间的通信 优点:可以实现任意关系的进程间的通信 缺点: 长期存于系统中,使用不当容易出错 缓冲区有限 无名管道:一种半双工的通信方式,只能在具有亲缘关系的进程间使用(父子进程) 优点:简单方便 缺点: 局限于单向通信 只能创建在它的进程以及其有亲缘关系的进程之间 缓冲区有限 信号量(Semaphore):一个计数器,可以用来控制多个线程对共享资源的访问 优点:可以同步进程 缺点:信号量有限 信号(Signal):一种比较复杂的通信方式,用于通知接收进程某个事件已经发生 消息队列(Message Queue):是消息的链表,存放在内核中并由消息队列标识符标识 优点:可以实现任意进程间的通信,并通过系统调用函数来实现消息发送和接收之间的同步,无需考虑同步问题,方便 缺点:信息的复制需要额外消耗 CPU 的时间,不适宜于信息量大或操作频繁的场合 共享内存(Shared Memory):映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问 优点:无须复制,快捷,信息量大 缺点: 通信是通过将共享空间缓冲区直接附加到进程的虚拟地址空间中来实现的,因此进程间的读写操作的同步问题 利用内存缓冲区直接交换信息,内存的实体存在于计算机中,只能同一个计算机系统中的诸多进程共享,不方便网络通信 套接字(Socket):可用于不同及其间的进程通信 优点: 传输数据为字节级,传输数据可自定义,数据量小效率高 传输数据时间短,性能高 适合于客户端和服务器端之间信息实时交互 可以加密,数据安全性强 缺点:需对传输的数据进行解析,转化成应用级的数据。 线程之间的通信方式 锁机制:包括互斥锁/量(mutex)、读写锁(reader-writer lock)、自旋锁(spin lock)、条件变量(condition) 互斥锁/量(mutex):提供了以排他方式防止数据结构被并发修改的方法。 读写锁(reader-writer lock):允许多个线程同时读共享数据,而对写操作是互斥的。 自旋锁(spin lock)与互斥锁类似,都是为了保护共享资源。互斥锁是当资源被占用,申请者进入睡眠状态;而自旋锁则循环检测保持者是否已经释放锁。 条件变量(condition):可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。 信号量机制(Semaphore) 无名线程信号量 命名线程信号量 信号机制(Signal):类似进程间的信号处理 屏障(barrier):屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从该点继续执行。 线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制