目录
一、exec函数族
二、system函数
三、popen函数
四、守护进程
4.1概念
4.2特点
4.3创建守护进程
一、exec函数族
功能:进程中调用exec函数族时,调用成功后,该进程当前内容被完全替换为新程序,可以实现父子进程执行不同的程序(即父进程创建子进程,子进程调用exec函数族,shell命令的源码逻辑也是如此)
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …);
@param: path 新程序绝对路径 若新程序和当前程序在同一目录可直接写程序名
arg 新程序的参数列表 (第一个参数不重要但是得有,""即可)后面就跟程序所需的参数,最后以NULL结尾
file 执行的程序名,(指定去PATH中找),前提是PATH中有,用的少...比较繁琐
@return:调用新程序成功后不返回,如果新程序有结果输出会输出到stdout
失败返回-1,并从源程序的调用点往下接着执行
echo $PATH 查看当前环境变量(系统找不到文件会默认去这里面找)
export PATH=[原环境变量]:[要加的路径] 或 $PATH:[要加的路径] ($引用的意思) 加进去的环境变量仅对当前窗口生
int execv(const char *path, const char *arg[], …);
int execvp(const char *file, const char *arg[], …);
与前面的不同在于,参数列表给指针数组地址即可,需要提前把参数放进指针数组
二、system函数
(exec函数使用起来比较麻烦,因此用得也比较少,用得多的有system和popen)
封装好的execl,方便好用,缺点是只能执行当前目录下的程序,其他目录下的程序需要加路径到环境变量里去),而且进程内容不是完全替换为新程序,而是先去执行新程序,执行完回来接着执行原内容
int system(char *command)
@param: command 要执行的程序参数列表(当作shell窗口输入 每个参数用字符串形式)
@return 调用成功返回进程的状态值,失败返回-1
三、popen函数
比system函数好在可以获取新进程的输出结果,我们可以把新进程的输出结果读写到文件中(fread读到数组保存,fwrite写到新文件)
FILE *popen(char *command,const char *type)
@param: command 要执行的程序参数列表(当作shell窗口输入)
type "r" 表示我们要读取输出,后续可循环利用fgets读出结果
@return: 运行结果以文件流形式返回
//示例
#include <stdio.h>
int main() {
FILE *fp;
char buffer[1024];
fp = popen("ls -l", "r");
if (fp == NULL) {
printf("Failed to run command\n");
return 1;
}
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
printf("%s", buffer);
}
pclose(fp);
return 0;
}
注意使用pclose关闭!
四、守护进程
4.1概念
又叫精灵进程,它是一个后台进程,生存期较长,独立于任何控制终端(无法切换到前台,终端关闭也不影响),并且周期性的执行某种任务或等待处理特定事件。
4.2特点
它是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。
进程组:进程的集合,进程组长是相关联进程中的父进程,其PID也是进程组ID,也可通过getpgid(getpid())获取
会话:进程组的集合,也可以理解成终端,会话ID通过getsid(getpid())获取
控制终端:由于在 Linux 中,每一个系统与用户进行交流的界面称为终端(shell窗口,本身也是一个控制进程),每一个从此终端启动的进程都依附于这个终端,终端也称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
4.3创建守护进程
(1)通过命令行简单创建: nohup xxx &
(2)具体创建:
- 创建父子进程,让父进程退出,则子进程变为孤儿进程(不退出),接着被init进程收养
- 子进程创建新会话setsid(),成功返回会话ID失败返回-1,使子进程脱离原终端
- 更改当前目录(因为守护进程一直运行在后台,其工作目录不能被卸载),一般chdir("/")
- 重设文件权限掩码为0——umask(0),(为了使守护进程创建文件时具有合适的权限),失败返回值<0
- 关闭从父进程继承的打开文件(stdin、stdout、stderr)