1、进程:
①进程是运行的程序在内存中的镜像,是运行起来的程序
②一个运行的程序可以产生多个进程,一个进程对应一个程序
③进程是并发的执行流程,并发是指单核cpu,宏观上程序同时运行,微观上只是一个程序在运行
④进程间相互独立,各自有各自的运行空间
2、进程控制块(pcb,内存的一块临时空间):
①包含进程号、优先级、文件列表、信号列表等
②进程结束了,pcb回收,进程号回收,进程号是有限的,回收后重新分配给其他新运行的进程
3、进程三种最基本的状态:就绪,运行,阻塞,(开始,结束)
4、进程的调度算法:先来先服务、短作业优先、优先级、时间片轮转、多级队列复合调度算法
5、进程创建,子进程结束后,他的资源回收一般有父进程来完成
int main(int argc, char *argv[])
{
//获得进程本身的进程号:getpid()
//获得进程父进程的进程号:getppid()
printf("before fork: pid=%d, parent pid=%d\n", getpid(), getppid());
int i = 0;
char caMsg[64] = {'\0'};
//创建子进程,子进程会对父进程进行原样拷贝(代码,运行状态(变量,运行位置等))
// 对父进程的输出缓存进行了拷贝,若缓冲中无\n,则多拷贝一次缓存数据
//遇到'\n' 缓冲区的数据输出
//程序正常结束,缓冲区的数据输出
//强制刷新,将缓冲区的数据输出
//缓冲区满了,缓冲区的数据输出
pid_t pid = fork();
//父子进程是两个相互独立的进程
if (pid > 0) //父进程中fork函数返回的是子进程的进程号
{
//海量代码
i = 3;
//若父进程正常结束,且优先于子进程结束,则子进程变成孤儿进程,由祖宗进程接管,资源 由祖宗进程回收
strcpy(caMsg, "this is parent.");
}
else if (0 == pid) //子进程中返回的是0
{
//海量代码
i = 6;
strcpy(caMsg, "this is child.");
}
else if (-1 == pid)
{
//创建子进程失败
perror("fork");
exit(EXIT_FAILURE);
}
for (; i>0; i--)
{
printf("%s pid=%d, ppid=%d\n", caMsg, getpid(), getppid());
sleep(1);
}
return 0;
}
6、僵尸进程:
子进程结束了,但是父进程没有对子进程进行资源回收,没有对子进程收尸
此时此刻的子进程即为僵尸进程,占用的资源一直占用,直到父进程对其收尸
若系统中存在大量的僵尸进程,则会导致系统没有资源分配给新的程序运行
int main(int argc, char *argv[])
{
//创建十个子进程,并让子进程变成僵尸
pid_t pid = -1;
int i = 0;
for (i=0; i<10; i++)
{
pid = fork();
if (pid > 0) //父进程中fork函数返回的是子进程的进程号
{
continue;
}
else if (0 == pid) //子进程中返回的是0
{
break;
}
else if (-1 == pid)
{
//创建子进程失败
perror("fork");
exit(EXIT_FAILURE);
}
}
if (pid >0)
{
//挂起父进程
pause();
}
printf("pid=%d, ppid=%d\n", getpid(), getppid());
return 0;
}
解决僵尸进程问题,①添加wait(NULL)函数,等待父进程对其进行收尸
②在子进程中再创建子进程,将子进程变成孤儿进程
for (i=0; i<10; i++)
{
//wait:阻塞等待子进程结束并收尸
printf("对%d子进程收尸\n", wait(NULL));
}
7、代码执行已存在的命令、程序
int main(int argc, char *argv[])
{
// myfork testfile
//新的进程会将当前进程替换掉,但是仍然使用当前进程的进程号,鸠占雀巢
//execl("/bin/ls", "ls", "-a", "-l", "/usr/include", NULL);
//到系统环境变量PATH中去找可执行文件,找到了就执行,没找到就失败
//execlp("ls", "ls", "-a", "-l", "/usr/include", NULL);
//execl("/opt/Qt5.14.2/Tools/QtCreator/bin/qtcreator", "qtcreator", NULL);
//execlp("qtcreator", "qtcreator", NULL);
//execl("/home/myfork", "myfork", "testFile", NULL);
//要执行自己写的文件,方法有两种
//1,将可执行文件放入系统环境变量PATH的中某个路径中
//2,将可执行文件的路径添加到系统环境变量PATH中
// sudo vim /etc/profile
// 在文件末尾添加 export PATH=pathname:$PATH
// 让配置生效 source /etc/profile
execlp("myfork", "myfork", "testFile", NULL);
printf("hello world\n");
return 0;
}
另:execv、execvp是将参数加入集合,然后执行
8、system()函数执行命令,直接将执行命令传入该函数即可