文章目录
- 一、代码替换函数
- (一)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,休眠态,且是进程组组长;