1.进程的基本概念:
问:什么是程序,什么是进程,区别是什么?
答:程序是静态概念,比如gcc test1.c -o a.out,那么a.out就是程序
进程是动态概念,就是程序运行起来后,系统中就多了一个进程
问:如果在Linux下查看系统的进程?
答:ps指令:展示一小部分的进程
ps -aux指令:展示几乎所有的进程(但是往往又用不到这么些)
所以我们通常采用ps和grep配合使用的方式来过滤掉一些无用进程,来获取有效信息(Linux中有一个管道,将-aux中的内容顺着管道,在管道末尾进行grep过滤,过去有用的东西):
ps -aux|grep xxx指令:
top指令:相当于是Windows下的任务管理器(是一个动态的界面)
问:什么是进程标识符?
答:每个进程都有一个非负整数表示唯一的ID,叫做pid(类似文件标识符)
Pid = 0:成为交换进程(swapper)
作用是:进程调度(分配内存,CPU占有率等)
Pid = 1:init进程
作用是:系统初始化(读取配置文件,调用其他进程等)
getpid函数:
调用该函数会返回进程的标识符
包含于头文件:
#include <sys/types.h>
#include <unistd.h>
简单的样例:
pid_t pid;
pid = getpid();
问:什么是父进程?什么是子进程?
答:进程A创建了进程B,A就是父进程,B就是子进程
问:C语言的程序空间是如何分配的?
答:如图所示:
2.进程的创建:
创建进程的函数fork:
函数原型:
pid_t fork(void);
fork如果调用成功了的话,会返回两个值:
返回值为0 代表当前进程是子进程
返回值为非负数 代表当前进程是父进程(返回的值是子进程的pid)
返回值为-1 代表调用失败
test1.c的代码如图:
int main(){
pid_t pid;
pid = getpid();
printf("The pid of my process is %d\n",pid);
return 0;
}
运行结果如图所示:
通过运行结果我们知道一个问题就是每次创建一个进程。他的pid都是不一样的,是在变化的
test2.c的代码如图所示:
int main(){
pid_t pid;
pid = getpid();
fork();
printf("The pid of my process is %d\n",pid);
return 0;
}
运行结果如图所示:
这样奇怪的知识就增加了,为什么会打印两次?在做一个测试,来看看新打印出来的,fork出的进程和原进程是不是同一个进程,还是父子进程的关系?
test3.c代码如图:
int main(){
pid_t pid;
pid = getpid();
fork();
printf("The pid of my process is %d\n",pid);
printf("The pid of fork is %d\n",getpid());
return 0;
}
运行结果如图所示:
而在刚开始的时候自己编写test1.c时,出现了一个小错误,代码是这样的
int main(){
pid_t pid;
pid = fork();
printf("The pid of my process is %d\n",pid);
return 0;
}
运行结果是这样的,有没有发现其中的问题?
那就是fork返回的值是两个,一个是pid,一个是表明身份的 0(忘了的可以看一下我上面写的内容),0 表示的是子进程啊!这就说明在一个main函数中时fork出来的进程也会并发执行原来的程序,但是却是子进程!
3.子进程存储的方式:
早期Linux是直接将父进程中除了未初始化的数据,全部拷贝给子程序,代码段进行共享;但随着Linux内核的发展完善,现在则是写实拷贝,通俗说就是如果初始化的数据在后边未进行修改的话(保证父子进程数据独立),则共享同一块存储空间
4.创建子进程后程序都在做些什么:
fork之后,先给子进程开辟一块空间,随后系统进行程序调度,决定父与子谁先运行(父、子有可能先运行)
5.创建fork的目的:
- 父进程希望子进程复制自己的代码,同时执行不同的代码段。这种应用场景在网络服务进程中是很常见的——父进程等待客户端发来的服务请求,请求到达时,父进程调用fork来创建子进程,让子进程来处理这个服务请求,于此同时父进程继续等待下一个服务请求的到达。就是一个程序想要同时运行多段代码,但是一个程序正常=情况下是不可能完成的,所以创建出另外的程序帮自己来完成,就像鸣人影分身处理事务[doge])
- 一个进程要执行不同的程序,这对shell是常见的情况。在这种情况下,子进程从fork返回后要立即调用exec(暂时先了解)
今天最后写一个小程序来巩固以下,粗浅的模拟一下Socket[doge]:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(){
pid_t pid,upid;
int cmd;
while(1){
printf("Please input your command to this socket!\n");
scanf("%d",&cmd);
if(cmd == 1){
printf("Connecting......\n");
pid = fork();
if(pid == 0){
while(1){
printf("%d is connected\n",getpid());
sleep(3);
}
}else{
printf("Waiting for the next user!\n");
}
}else{
printf("ERROR!\n");
}
}
return 0;
}