1.进程相关概念
程序和进程
程序;是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu、内存、锁...)。
进程;是活跃的程序,占用系统资源。
程序->剧本 进程->场地、道具
并发
并发运行多道程序
2.CPU和MMU
虚拟空间:程序运行时产生
MMU:虚拟地址映射到实际物理地址上、修改内存的访问级别
访问级别:linux里设置了2种,0级(内核使用)和3级(用户使用)
3.进程控制块PCB
每个进程在内核中都有一个进程控制块,Linux内核的进程控制块是task_struct结构体。
- 进程id:系统中每个进程有唯一的id
- 进程状态:就绪、运行、挂起、停止等状态
- 进程切换时需要保存和恢复的一些CPU寄存器
- 描述虚拟地址空间的信息
- 描述控制终端的信息
- 当前工作目录
- umask掩码(保护文件创建或修改)
- 文件描述符表,包含很多指向file结构体的指针
- 和信号相关的信息
- 用户id和组id
- 会话(族连)和进程组(把功能相似的进程放在一起,方便管理)
- 进程可以使用的资源上限
4.环境变量
指在操作系统中用来指定操作系统运行环境的一些参数。通常有以下特征
1.字符串2.有统一的格式3.值用来描述进程环境信息
引入环境变量表:需声明环境变量。extern char** environ;
相关环境变量
PATH:记录可执行文件的搜索路径
echo $PATH
SHELL:记录当前所使用的命令解析器
echo $SHELL
TERM
//打印当前进程的所有环境变量
#include <stdio.h>
extern char** environ;
int main()
{
int i;
for(i = 0; environ[i]; i++) //存储形式:与命令行参数类似。char* []数组,NULL作为结束
{
printf("%d\n", environ[i]);
}
return 0;
}
getenv、setenv、unsetenv//删除
man getenv 查看一下
//使用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *val;
const cahr *name = "ABD";
val = getenv(name);
printf("1, %s = %s\n", name, val)
setenv(name, "haha-day-and-night", 1)
val = getenv(name);
printf("2, %s = %s\n", name, val);
if 0
int ret = unsetenv("ABCDEF);
printf("ret = %d\n", ret);
val = getenv(name);
printf("3, %s = %s\n", name, val);
#else
int ret = unsetenv("ABD"); //name=value:value
printf("ret = %d\n", ret);
val = getenv(name);
printf("3, %s = %s\n", name, val);
#endif
return 0;
}
5.进程控制
fork函数创建子进程
返回值2个:1.子进程的pid(非负整数>0) :父进程的返回
2.返回0 : 子进程的返回
循环创建N个子进程的架构
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid;
printf("xxxx\n");
pid = fork();
if(pid == -1)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
printf("I am child , pid = %u, ppid = %u\n", getpid(), getppid());//打印子进程 父进程
}
else
{
printf("I am parent, pid = %u, ppid = %u\n", getpid(), getppid());
sleep(1);
}
print("YYYY\n");
return 0;
}
//循环创建5个子进程的架构
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i;
pid_t pid;
printf("xxxx\n");
for(i = 0; i < 5; i++)
{
pid = fork();
if(pid == -1)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
//printf("I am %dth child , pid = %u, ppid = %u\n", i+1, getpid(), getppid());//打印子进程 父进程
break;
}
}
if(i < 5)
{
sleep(i);
printf("I am %dth child , pid = %u\n", i+1, getpid());//打印子进程 父进程
}
else
{
sleep(i);
printf("I am parent\n");
}
//print("YYYY\n");
return 0;
}
6.进程共享
刚fork之后:父子进程0~3g都相同,PCD中有不同。
父子进程间遵循读时共享写时复制的原则。
共享:1.文件描述符(打开文件的结构体)2.mmap建立映射区
fork之后父进程先执行还是子进程先执行不确定。取决于内核所使用的调度算法。
7.GDB 调试
gdb a.out 进行调试
b if i = 3; //设置条件断点
start
set follow-fork-mode child //跟踪子进程(默认跟踪父进程)
name //next 下一行