IO进程学习——5

一、进程

1.创建守护进程

1、创建子进程,父进程退出

​ fork(); //脱离中断控制

2、在子进程中创建新会话

​ setsid(); //使进程成为GROUP组长

3、改变当前目录为根目录

​ chdir(); //使进程文件不会被删除

4、重设文件权限掩码

​ umask(0); //放开所有权限

5、关闭文件描述符

​ close();

​ getdtablesize() //获取文件描述符表的大小

守护进程示例:

/*===============================================
 *   文件名称:daemon.c
 *   创 建 者:     
 *   创建日期:2025年08月08日
 *   描    述:
 ================================================*/
#include "head.h"

int daemon_init()
{
    /*1、创建子进程,父进程退出*/
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        return -1;
    } else if (pid > 0)
        exit(0);

    /*2、在子进程中创建新会话*/
    if (0 > setsid()) {
        perror("setsid");
        return -1;
    }

    /*3、改变当前目录为根目录 */
    if (0 > chdir("/tmp")) {
        perror("chdir");
        return -1;
    }

    /*4、重设文件权限掩码*/
    umask(0);

    /*5、关闭文件描述符 */
    int fd;
    for (fd = 0; fd < getdtablesize(); fd++)
        close(fd);

    return 0;
}

int main(int argc, char *argv[])
{ 
    if (0 > daemon_init()) {
        printf("Create daemon failed!\n");
        return -1;
    }

    FILE *fp = fopen("log.txt", "a+");
    if (NULL == fp)
        return -1;

    int lines = 0;
    char buf[1024];
    while (1) {
        if (NULL == fgets(buf, sizeof(buf), fp))
            break;
        if ('\n' == buf[strlen(buf)-1])
            lines++;
    }
    while (1) {
        fprintf(fp, "%-3d hello world!\n", ++lines);
        fflush(fp);
        sleep(1);
    }

    fclose(fp);

    return 0;
} 

二、线程

线程:轻量级的进程,是共享同一个进程空间的多个任务

1.线程创建

(1)pthread_create函数

头文件:

​ #include <pthread.h>

原型:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

作用:

​ 创建线程

参数:

​ thread:获取线程ID(TID - 线程号)

​ attr:线程属性,默认为NULL

​ start_routine:线程函数(参数与返回值都为void *类型)/回调函数

​ 需要用什么函数,就传什么函数名

​ arg:线程函数的参数

返回值:

​ 成功:0

​ 失败:返回error码

​ char *strerror(int errnum); //根据错误码获取错误信息

注意

使用线程的源文件编译时要加 -lpthread 参数

gcc xxxx -lpthread

(2)pthread_exit 退出函数

头文件:

​ #include <pthread.h>

原型:

	void pthread_exit(void *retval);

作用:

​ 结束线程,并获取线程函数返回值

参数:

​ retval:线程函数的返回值

(3)线程示例

/*===============================================
 *   文件名称:daemon.c
 *   创 建 者:     
 *   创建日期:2025年08月08日
 *   描    述:
 ================================================*/
#include "head.h"

int daemon_init()
{
    /*1、创建子进程,父进程退出*/
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        return -1;
    } else if (pid > 0)
        exit(0);

    /*2、在子进程中创建新会话*/
    if (0 > setsid()) {
        perror("setsid");
        return -1;
    }

    /*3、改变当前目录为根目录 */
    if (0 > chdir("/tmp")) {
        perror("chdir");
        return -1;
    }

    /*4、重设文件权限掩码*/
    umask(0);

    /*5、关闭文件描述符 */
    int fd;
    for (fd = 0; fd < getdtablesize(); fd++)
        close(fd);

    return 0;
}

int main(int argc, char *argv[])
{ 
    if (0 > daemon_init()) {
        printf("Create daemon failed!\n");
        return -1;
    }

    FILE *fp = fopen("log.txt", "a+");
    if (NULL == fp)
        return -1;

    int lines = 0;
    char buf[1024];
    while (1) {
        if (NULL == fgets(buf, sizeof(buf), fp))
            break;
        if ('\n' == buf[strlen(buf)-1])
            lines++;
    }
    while (1) {
        fprintf(fp, "%-3d hello world!\n", ++lines);
        fflush(fp);
        sleep(1);
    }

    fclose(fp);

    return 0;
} 

运行截图

alt