进程的认识
1.程序与进程之间的区别
程序就是没跑起来的进程 打开程序后,系统会生成一个进程
例如windows的桌面快捷方式就是一个程序 ,点击运行会生成一个进程
进程是程序的一次运行活动
通俗点的意思就是程序跑起来了,系统中多了一个进程
2.如何查看进程
在liunx下面使用 ps 指令进行查看
完整的是 ps -aux
但是显示的太多,需要筛查 配合grep来查找系统中的进程
ps-aux|grep init 直接筛选出来init的进程
或者使用top指令 类似windows的任务管理器
3.进程标识符 pid
每个进程都有一个唯一的非负整数表示唯一ID
叫做pid,类似与我们的身份证
pid=0;成为交换进程,表示进程调度
pid=1;表示init进程 作用系统的初始化
pid_t pid;
pid=getpid();
printf("pid=%d",pid);
getpid获得当前进程pid号
getppid获得父进程pid号
4.父进程子进程
如果进程A创建了进程B
那么进程A是父进程
进程B是子进程
C程序储存空间是如何分配的
BSS段 非初始化数据段 存放的是未初始化的全局变量和静态变量。
栈区:由操作系统自动分配和释放 ,存放函数的参数值,局部变量的值等。每当一个函数被调用时,该函数的返回类型和一些调用的信息也会被存放到栈中。
栈中 保存的是自动变量就是指在函数内部定义使用的变量。只能在函数内部使用它。自动变量是局部变量,即它的作用区域是在定义它的函数内部。
正文,也就是代码段,在低地址处 【 代码段】
初始化了的数据在正文的上面的地址 【数据段】
没有初始化的地址在初始化地址的上面 【bss段 非初始化数据段】
malloc开辟出来的空间在堆那个地方 【 堆】
书写的函数,都是保存在栈里面
函数的地址保存在栈里面
每次函数调用所保存的信息都保存在这里 【 栈】
int(里面的参数) 命令行参数和环境变量
int a = 0; //全局初始化区
char *p1; //全局未初始化区
void main()
{
int b; //栈
char s[] = “abc“;//栈
char *p2; //栈
char *p3 = “123456“; //123456\0在常量区,p3在栈上;体会与 char s[]="abc"; 的不同
static int c =0; //全局初始化区
p2 = (char *)malloc(20); //堆区
strcpy(p1, “123456“); //123456\0在常量区,编译器可能将它与p3指向的 “123456 “优化成一块
创建进程函数fork vfork
进程创建函数fork
pid_t pid1;
pid1=getpid();
printf("当前的pid号是%d\n",pid1);
fork(); //创建父子进程
if(pid1==getpid()){
printf("这是父进程\n");
}else{
printf("这是子进程,子进程的pid号是%d\n",getpid());
}
可以使用创建两个进程 进行比较
pid_t pid1;
pid_t pid2;
pid1=getpid(); //最开始使用getpid函数 获得最开始的pid
fork(); //使用fork创建
pid2=getpid(); //得到pid2 的pid号 判断是子进程还是父进程
if(pid1==pid2){
printf("这是父进程\n");
}else{
printf("这是子进程,子进程的pid号是%d\n",getpid());
}
需要注意!!
子进程创建成功后,fork是返回两个值,一个代表父进程,一个代表子进程:
返回值非负数,代表父进程
返回值为,代表子进程
调用失败返回 -1;
创建成功fork后 会创建出来子进程
pid_t pid1;
pid_t retpid;
pid=getpid();
retpid=fork();
if(retpid>0){
printf("创建出来了父进程 pid号是 %d retpid是%d\n",getpid(),retpid);
}else{
printf("创建了子进程 pid号是 %d retpid是 %d\n",getpid(),retpid);
}
执行结果
创建出来了父进程 pid号是 28427 retpid是28428
创建了子进程 pid号是 28428 retpid是 0
通过运行结果可以看出 父进程的pid是28427 通过父进程创建出来子进程的pid号
子进程的pid号是父进程创建出来的 并且子进程的fork的返回值为0
进程创建fork
使用的是把所有的文件都从父进程拷贝到子进程
而新的是如果子进程不改变a的大小 他们两个进行a的共享
只有子进程对a动手脚的时候才会采用在子进程的内存空间里面备份一个a
1.创建子进程的目的
2.创建一个简单的服务器进程 使用子进程进行对接
在linux里面while使用printf要加入换行符才能显示出来
pid_t pid;
int data;
while(1){
printf("请输入来的人的序号\n");
scanf("%d",&data);
if(data==1){
pid=fork();
if(pid==0){
while(1){
printf(" %d \n ",getpid()); //没有加入换行符显示不出来
sleep(2);
}
}
}else{
printf("wait !!!!\n");
}
}
return 0;
}
执行的结果
this is child getpid=12684//新创建的
this is child getpid=12682//第一次创建的
this is child getpid=12684
1
please data
this is child getpid=12685//新创建的
this is child getpid=12682//第二次创建的
this is child getpid=12684//第一次创建的
3.总结fork
fork进程会返回两个返回值,父进程的返回值是子进程的pid号 子进程的返回值是0
vfork函数
vfork 直接使用父进程的内存空间 (需要使用exit正常退出的时候 父进程才会使用到子进程使用的父进程的空间)影响的只是那个让他正常退出的值
vfork 函数创建进程会让子进程先执行,子进程执行完成后调用exit退出后,父进程才执行。
pid_t pid;
int data=0;
int i=3;
pid=vfork();
if(pid==0){
while(1){
data++;
i=4; //在这里使用给i定义 不能加int
printf("这是子进程 pid= %d data =%d\n",getpid(),data);
sleep(2);
if(data==3){ //打印出来会影响data的值
exit(1);
}
}
}else{
while(1){
printf("这是父进程 pid= %d data=%d\n",pid,data);
printf("i=%d\n",i);
sleep(1);
}
}
输出的结果 i=4 data =3 子进程改变的值影响了子进程的值。