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_WRONLY|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");
            fflush(stdout);
            sleep(1);
        }
        return 0;
    }
    return 0;
}

  • 注:将stdin和stdout重定向到文件后,不再适用于行缓冲,而是全缓冲,因此此时遇到’\n’不能刷新缓冲区,所以此处采用手动刷新的方式
    在这里插入图片描述
    上图可见,该进程的父进程为1号init进程;
    依赖终端"?"代表不依赖终端;
    进程状态为Ss,休眠态,且是进程组组长;
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值