IO进程线程(七)代码替换函数、守护进程

一、代码替换函数

(一)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,休眠态,且是进程组组长;

相关推荐

  1. 23111 IO进程线 day6

    2024-06-09 00:30:01       35 阅读
  2. IO进程线 day7

    2024-06-09 00:30:01       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-09 00:30:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-09 00:30:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-09 00:30:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-09 00:30:01       18 阅读

热门阅读

  1. 阿里云计算之运维概念学习笔记(一)

    2024-06-09 00:30:01       10 阅读
  2. C++中的模板---下

    2024-06-09 00:30:01       8 阅读
  3. 分布式Shiro,SpringBoot项目Shiro整合Redis

    2024-06-09 00:30:01       9 阅读
  4. 【SpringBoot】打包成Docker镜像后日志输出中文乱码

    2024-06-09 00:30:01       10 阅读
  5. Leetcode:删除链表的倒数第N个结点

    2024-06-09 00:30:01       7 阅读
  6. 开发指南028-生成二维码

    2024-06-09 00:30:01       8 阅读
  7. C++day3

    C++day3

    2024-06-09 00:30:01      7 阅读
  8. 用户价值模型-RFM模型

    2024-06-09 00:30:01       8 阅读
  9. 汇编语言-----开始到寄存器

    2024-06-09 00:30:01       6 阅读
  10. 30分钟快速入门TCPDump

    2024-06-09 00:30:01       7 阅读
  11. WHAT - 发布订阅

    2024-06-09 00:30:01       8 阅读
  12. Chrome DevTools攻略:提升开发效率的利器

    2024-06-09 00:30:01       10 阅读