文章目录
- 一、代码替换函数
- (一)system函数
- (二)exec函数族
- 二、守护进程
- (一)创建
- 1. 脱离父进程影响
- 2. 脱离原会话组和进程组的影响
- 3.修改进程工作目录
- 4. 修改进程创建文件的掩码
- 5. 关闭从父进程继承的文件描述符
- 6. 将标准输入、标准输出、标准出错都重定向到文件中
- 7. 让守护进程随系统启动而启动
- (二)应用实例
一、代码替换函数
(一)system函数
#include <stdlib.h>
int system(const char *command);
功能:
使用fork创建一个子进程 在子进程中执行shell命令
参数:
command:要执行的命令字符串 例如:"ls -l" "./b.out"
返回值:
如果command为NULL 终端可用返回非0 终端不可用返回0
如果子进程创建失败 返回 -1 重置错误码
如果命令都执行成功了返回的就是子进程退出的状态值
- 注:调用system函数时,进程会阻塞等待system函数调用结束后再继续执行
#include <my_head.h>
int main(int argc, const char *argv[])
{
printf("----start----\n");
//执行shell命令
system("ls -l");
printf("-----end-----\n");
return 0;
}
输出结果:
(二)exec函数族
int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *pathname, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
二、守护进程
相当于系统的服务,它会随着系统启动而启动,随着系统的终止,脱离了终端
(一)创建
1. 脱离父进程影响
创建子进程,父进程退出
使子进程变成孤儿,被init进程收养
2. 脱离原会话组和进程组的影响
调用setsid来创建新的会话组和进程组
#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
功能:
如果调用进程不是进程组组长,会创建一个新的会话和进程组
调用进程变成新会话和进程组中的唯一进程
新的会话id和进程组id 都等于调用进程的pid
参数:无
返回值:
成功 新的会话id
失败 -1 重置错误码
3.修改进程工作目录
改到一个不会被删除和卸载的目录下
#include <unistd.h>
int chdir(const char *path);
功能:修改进程的工作目录
参数:path:新的目录
返回值:
成功 0
失败 -1 重置错误码
4. 修改进程创建文件的掩码
控制进程创建的文件的最大权限
每个进程有自己的掩码
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
功能:修改进程创建文件的掩码
参数:mask:新的掩码
返回值:总是会成功 返回之前的掩码
5. 关闭从父进程继承的文件描述符
6. 将标准输入、标准输出、标准出错都重定向到文件中
因为守护进程不应该和终端有关联
#include <unistd.h>
int dup(int oldfd);
功能:重定向文件描述符 将 返回值(遵循最小原则)产生新文件描述符
重定向到oldfd中
参数:oldfd:旧的文件描述符
返回值:
成功 产生新文件描述符(遵循最小原则)
失败 -1 重置错误码
#include <unistd.h>
int dup2(int oldfd, int newfd);
功能:将newfd重定向到oldfd中
参数:
oldfd:旧的文件描述符
newfd:新的文件描述符
返回值:
成功 newfd
失败 -1 重置错误码
7. 让守护进程随系统启动而启动
如果想让自己的守护进程随着系统的启动而启动
可以 把执行进程的命令 放在系统启动的过程中会执行的脚本中 如 /etc/profile
(二)应用实例
#include <my_head.h>
int main(int argc, char const *argv[])
{
pid_t pid = 0;
//1. 脱离父进程
pid = fork();
if(-1 == pid){
ERR_LOG("pid error");
}else if(0 < pid){//父进程
exit(0);//退出父进程
}else if(0 == pid){//子进程
//2. 脱离原来的会话组
setsid();//调用进程成为一个新的会话组组长
//3. 修改进程的工作目录
chdir("/home/linux/");
//4. 修改进程创建文件的最大权限
umask(0002);
//5. 关闭文件描述符
for(int i=0;i<1024;i++){
close(i);
}
int log_fd = open("/home/linux/05work/07day/log.txt",O_CREAT|O_APPEND,0666);
if(-1 == log_fd) ERR_LOG("open error");
//6. 标准输入、标准输出、标准出错都重定向到文件中
dup2(log_fd,0);
dup2(log_fd,1);
dup2(log_fd,2);
//开启自己的服务
while(1){
printf("hello world\n");
sleep(1);
}
return 0;
}
return 0;
}
上图可见,该进程的父进程为1号init进程;
依赖终端"?"代表不依赖终端;
进程状态为Ss,休眠态,且是进程组组长;