一、进程控制
首先了解CPU时间片的概念:
CPU 会给每个进程被分配一个时间段,进程得到这个时间片之后才可以运行,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,CPU 的使用权将被收回,该进程将会被中断挂起等待下一个时间片。如果进程在时间片结束前阻塞或结束,则 CPU 当即进行切换,这样就可以避免 CPU 资源的浪费。
进程的创建:
进程的ID为pid_t类型,本质是一个正整数
包含的头文件:
#include<sys/types.h>
#include<unistd.h>
相关操作:
获取当前进程ID(PID):
pid_t getpid(void)
获取当前进程的父进程ID(PPID):
pid_t getppid(void)
创建一个新的进程:
pid_t fork(void)
这里主要解析fork函数:
fork函数调用成功之后,会返回两个值,父子进程之间的返回值是不同的。
父进程的虚拟地址空间将该返回值标记为一个大于0的数(其实记录的就是子进程的ID)
子进程的虚拟地址空间中将该返回值标记0
在程序中一般是通过fork的返回值来判断当前进程是父进程还是子进程
示例:
int main()
{
// 在父进程中创建子进程
pid_t pid = fork();
printf("当前进程fork()的返回值: %d\n", pid);
if(pid > 0)
{
// 父进程执行的逻辑
printf("我是父进程, pid = %d\n", getpid());
}
else if(pid == 0)
{
// 子进程执行的逻辑
printf("我是子进程, pid = %d, 我爹是: %d\n", getpid(), getppid());
}
else // pid == -1
{
// 创建子进程失败了
}
// 不加判断, 父子进程都会执行这个循环
for(int i=0; i<5; ++i)
{
printf("%d\n", i);
}
return 0;
}
循环创建进程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main()
{
pid_t pid;
// 在循环中创建子进程
for(int i=0; i<3; ++i)
{
pid = fork();
if(pid > 0)
{
sleep(3);
}
else if(pid == 0)
{
// 不让子进程执行循环, 直接跳出
break;
}
}
printf("当前进程pid: %d\n", getpid());
return 0;
}
需要注意的是:
两个进程中是不能通过全局变量实现数据交互的,因为每个进程都有自己的地址空间,两个同名全局变量存储在不同的虚拟地址空间中,二者没有任何关联性。如果要进行进程间通信需要使用:管道,共享内存,本地套接字,内存映射区,消息队列等方式。
exec族函数:
需求:需要通过一个进程启动另外一个进程,那么这种情况下需要使用exec族函数
函数原型:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...
/* (char *) NULL */);
int execlp(const char *file, const char *arg, ...
/* (char *) NULL */);
int execle(const char *path, const char *arg, ...
/*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
char *const envp[]);
execl():
该函数可用于执行任意一个可执行程序,函数需要通过指定的文件路径才能找到这个可执行程序
#include<unistd.h>
int execl(const char* path,const char* arg,....)
参数:
path:要启动的可执行程序的路径
arg: 启动的进程的名字,可以随意指定,一般和要启动的可执行程序名相同
....:要执行的命令需要的参数,可以写多个,最后以 NULL 结尾,表示参数指定完了。
返回值:如果这个函数执行成功,没有返回值,如果执行失败,返回 -1
execlp()函数:
该函数常用于执行已经设置了环境变量的可执行程序,函数中的 p 就是 path,也是说这个函数会自动搜索系统的环境变量 PATH,因此使用这个函数执行可执行程序不需要指定路径,只需要指定出名字即可。
int execlp(const char *file, const char *arg, ...);
参数:
file: 可执行程序的名字
在环境变量 PATH 中,可执行程序可以不加路径
没有在环境变量 PATH 中,可执行程序需要指定绝对路径
arg: 启动的进程的名字,可以随意指定,一般和要启动的可执行程序名相同
... : 要执行的命令需要的参数,可以写多个,最后以 NULL 结尾,表示参数指定完了。
返回值:如果这个函数执行成功,没有返回值,如果执行失败,返回 -1
函数的使用:
‘