gcc -v 打印编译信息
file a.out 查看本质 链接架构等
./a.out 抛给加载器 运行时的加载器是操作系统中的程序,当我们去执行一个程序时,加载器负责将这个程序加载到内存中去执行这个程序。
程序在编译链接时用链接器,运行时用加载器,这俩队程序运行原理非常重要
程序结束: return exit _exit
非正常终止:自己或他人发信号终止进程(类似ctrl c)
atexit 注册进程终止处理函数
多个注册时,先进后出 先注册的后执行
用_exit时,不执行atexit注册的进程终止处理函数
#include<stdio.h>
#include<stdib.h>
void func1(void)
{
printf("sasasa");
}
int mian(void)
{
printf("5551as");
//当进程被正常终止时,系统会自动调用这里注册的func1执行
atexit(func1);
return 0;
}
进程环境
环境变量:export查看环境变量
进程环境表:每个进程中都有一份所有环境变量构成的一个表格 (字符串数组)
程序通过environ全局变量使用环境变量,用environ变量指向进程环境表
#include<stdio.h>
int main(void)
{
extern char **environ;
int i = 0;
while(NULL != environ[i])
{
printf("%s\n",environ[i]);
i++;
}
return 0;
}
获取指定环境变量函数 getenv
进程运行的虚拟地址空间
操作系统中的每个进程在独立地址空间中运行
虚拟地址到物理地址空间的映射
为了 进程隔离 提供多进程同时运行
进程 程序的一次运行过程 生命周期为开始执行这个程序到程序执行完
进程是动态过程而不是静态实物
进程控制块PCB 内核中专门用来管理一个进程的数据结构
进程ID 数字编号 PS打印当前进程
多进程调度原理 调度以进程为单位
操作系统同时运行多个进程
宏观上的并行和微观上的串行
实际上操作系统最小的调度单元是线程而不是进程
fork创建子进程
多进程实现了宏观上的并行
fork内部原理:进程的分裂生长模式,若操作系统需要一个新进程来运行一个程序,那么操作系统会用一个现有的进程来复制生成一个新进程
fork函数调用一次会返回两次,返回值为0为子进程,大于0为父进程
fork 父进程的返回值是子进程的进程ID
#include<stdio.h>
#include <unistd.h>
int main(void)
{
pid_t p1 = -1;
p1 = fork(); //返回两次
if(p1 ==0)
{
//子进程
printf("%d\n",getpid());
printf("hello \n");
}
if(p1 > 0)
{
//父进程
printf("%d\n",getpid());
printf("world \n");
}
return 0;
}
子进程
子进程和父进程是两个独立的个体
子进程有独立的PCB
子进程被内核同等调度
父子进程对文件的操作
上下文父进程先open打开一个文件得到fd,然后再fork创建子进程。之后再父子进程中各自write向fd中写入内容
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdlib.h>
int main(void)
{
int fd = -1;
pid_t pid = -