进程的认识
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函数 获得最开始的pidfork(); //使用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=126841please datathis 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 子进程改变的值影响了子进程的值。