进程?
程序执行时,会建立进程使用系统资源,系统资源主要值cpu和内存等。
换句话说,进程是正在执行的程序实例。执行程序是,内核会将程序载入虚拟内存。
1、进程的内存布局包括:
- 文本:程序的指令
- 数据:程序使用的静态变量
- 堆:程序可从该区域动态分配额外内存
- 栈:随着函数的调用、返回而增减的一片内存。
2、进程的单道程序设计模型和多道程序设计模式。进程控制块的本质:task_struct结构体
其中多道程序设计模型:A,B,C这多个程序将自己的任务分为多个时间轮片,然后CPU将时间轮片分配给一个程序,然后通过时钟中断来收回时间轮片。时钟中断对进程是不可抗拒的,CPU通过时间轮片控制每一个程序执行。以此,达到几个程序都在使用cpu。
实现并发的理论依据:时钟中断机制。
3、CPU的基本结构:存储介质-》网络-》内存-》cache-》cache-》寄存器。
- 寄存器(cpu里面):32位cpu就是4字节,64位就是6字节.
- cache缓存:进一步提高内存的缓存速度。
- 内存:cpu速度很快,但是磁盘很慢,所以要使用cache。它的存储容量小但是速度快
- 其中,cpu内部包括:预取指令,译码器,执行(算术逻辑单元),寄存器堆,内存管理单元(MMU)。
- MMU包括:物理内存和虚拟内存。mmu负责物理内存与虚拟内存之间的一一对应关系。我们写错程序时只是用虚拟内存。cpu在访问内存区域时会设置访问级别:0-3。但是linux只使用了3级(最低)和0级(最高)。MMU会将内存完成映射,并设置其级别。
- 进程控制块,PCB:linux内核的进程描述结构体,主要包括:进程pid;进程状态,包括初始化、就绪、运行、挂起、终止,就绪是进程在等待CPU,进程得到cpu之后即可运行,然后是挂起就是进程放弃cpu;进程切换时需要保存和恢复的CPU寄存器的值;描述虚拟地址空间的信息;当前终端;当前工作目录;UMASK保护文件创建;文件描述符表,每一个文件描述符是一个数,描述文件的句柄,可通过它找到文件;和信号相关的信息;用户id和组id;会话session和进程组;进程可使用的资源上限。
4、环境变量
linux是什么样的操作系统:多任务、多用户;
为了对每个用户个性化使用,配置自己的参数。因此,通过配置环境变量来在操作系统中指定操作系统运行环境的一些参数。特征包括:
- 字符串(本质);每个字符串通过名称=值的形式定义。一年春,环境是名称-值的成对集合;通过命令:$PATH , echo shell,
- 每一个进程都有与之相关的称之为环境列表。
- 有同一的格式,存储形式与命令行类似;使用形式与命令行相似;以NULL为结束标记
- 引入环境变量表,须要声明环境变量:extern char **environ;
- 如:打印当前进程的所有的环境变量。
#include <stdio.h>
extern char **environ ;
int main(int argc, char *argv[]){
printf("Hello World!!!\n");
int i;
for (i=0; environ[i]!=NULL; i++){
printf("%s \n", environ[i]);
}
return 0;
}
与环境变量相关的函数:getenv,setenv。
5、进程控制fork
返回值有2个:1、返回子进程的pid;返回0。返回值大于0是父进程,等于0是子进程。
执行多个子进程,见例子:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
printf("first line \n") ;
pid_t pid;
int i;
for (i = 0; i < 5; i++)
{
pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}else if(pid == 0)
{
// 执行子进程的逻辑
break;
}else{
}
}
if(i < 5){
sleep(i);
printf("In the %d child = %u, ppid = %u \n",i+1,getpid(), getppid());
}else{
sleep(i);
printf("i am parent");
}
return 0;
}
子进程和父进程抢占cpu资源时处于同等的地位。因此,fork之后,谁先执行谁后执行是随机争夺抢占cpu。为了保证执行的先后顺序,可以通过休眠、阻塞等方式。
进程共享
通过进程共享时,有哪相同和不同之处?
相同:全局变量、data、text、栈、环境变量、
不同:进程id,fork返回值,进程运行,全局变量是独享、闹钟。真实的策略是:读时共享、写是复制的原则。
子进程是从父进程的fork之后再开始执行代码的。
那么父子进程在共享什么?文件描述符(打开文件的结构体)、mmap建立的映射区。
exec函数:如果在子进程中调用了exec函数,子进程的用户空间代码和数据会被完全替换为新的程序的内 存,但是不会创建新的进程。
其中:有六种exec函数:
- execlp 函数,l为list,p为past.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc