Linux程序开发(六):进程编程和系统日志守护进程

news2024/12/25 0:20:26

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊!

喜欢我的博客的话,记得点个红心❤️和小关小注哦!您的支持是我创作的动力!数据源存放在我的资源下载区啦!

Linux程序开发(六):进程编程和系统日志守护进程

目录

  • Linux程序开发(六):进程编程和系统日志守护进程
    • 1. 编程题(任选3道)
      • 1.1. 编写一个程序,创建两个子进程,父进程在屏幕上输出“I am parent process.”,两个子进程分别输出” I am child process 1.”、” I am child process 2.”,要求父进程在两个子进程输出完字符后再输出自己的字符。
      • 1.2. 父进程创建3个子进程,3个子进程需要打开文件a.txt并写入字符串,要求字符串能表明身份同时写明自己的进程号,最后父进程需要在该文件里面写入“I am father process, mypid is”+进程号。要求不能产生僵尸进程。
      • 1.3. 有爷爷爸爸孙子三人一起工作,前两秒三人一起休息讨论工作,之后爷爷每2秒休息一次,爸爸每4秒休息一次,儿子每6秒休息一次,请按照关系创建父子进程,每人每次休息时都打印他的身份、进程pid以及当前时间,工作时间为18s。
      • 1.4. 编写程序让两个子进程交替判断一个范围内的整数是不是素数。运行程序时要输入两个参数,一个是左边界,一个是右边界。比如说判断100到200之间哪些是素数,子进程1判断100是不是素数,子进程2判断101是不是素数,子进程1再判断102是不是素数,子进程2判断103是不是素数...,一直轮流下去。
      • 1.5. 仿照讲义中的“系统日志守护进程”例子,写一个守护进程,每隔一段时间获取当前登录用户名,将获取到的信息加上当前时间写入系统日志。

1. 编程题(任选3道)

1.1. 编写一个程序,创建两个子进程,父进程在屏幕上输出“I am parent process.”,两个子进程分别输出” I am child process 1.”、” I am child process 2.”,要求父进程在两个子进程输出完字符后再输出自己的字符。

编写c语言程序processes.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
    pid_t child1, child2;

    child1 = fork(); // 创建第一个子进程

    if (child1 == 0) {
        // 子进程1
        printf("I am child process 1.\n");
    } else {
        child2 = fork(); // 在父进程中创建第二个子进程

        if (child2 == 0) {
            // 子进程2
            printf("I am child process 2.\n");
        } else {
            // 等待两个子进程结束
            wait(NULL);
            wait(NULL);

            // 父进程
            printf("I am parent process.\n");
        }
    }

    return 0;
}

使用gcc编译器进行程序编译

gcc -o process process.c

在这里插入图片描述

运行程序

./process

在这里插入图片描述

1.2. 父进程创建3个子进程,3个子进程需要打开文件a.txt并写入字符串,要求字符串能表明身份同时写明自己的进程号,最后父进程需要在该文件里面写入“I am father process, mypid is”+进程号。要求不能产生僵尸进程。

在linux上编写c语言程序process.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() {
    // 打开文件a.txt,如果不存在则创建
    int fd = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    pid_t child1, child2, child3;

    child1 = fork(); // 创建第一个子进程

    if (child1 < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (child1 == 0) {
        // 子进程1
        char str[] = "I am child process 1, mypid is ";
        char pid[10];
        sprintf(pid, "%d", getpid());
        strcat(str, pid);
        write(fd, str, strlen(str));
        close(fd);
        exit(0);
    } else {
        child2 = fork(); // 创建第二个子进程

        if (child2 < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (child2 == 0) {
            // 子进程2
            char str[] = "I am child process 2, mypid is ";
            char pid[10];
            sprintf(pid, "%d", getpid());
            strcat(str, pid);
            write(fd, str, strlen(str));
            close(fd);
            exit(0);
        } else {
            child3 = fork(); // 创建第三个子进程

            if (child3 < 0) {
                perror("fork");
                exit(EXIT_FAILURE);
            } else if (child3 == 0) {
                // 子进程3
                char str[] = "I am child process 3, mypid is ";
                char pid[10];
                sprintf(pid, "%d", getpid());
                strcat(str, pid);
                write(fd, str, strlen(str));
                close(fd);
                exit(0);
            } else {
                // 等待三个子进程结束
                waitpid(child1, NULL, 0);
                waitpid(child2, NULL, 0);
                waitpid(child3, NULL, 0);

                // 父进程
                char str[] = "I am father process, mypid is ";
                char pid[10];
                sprintf(pid, "%d", getpid());
                strcat(str, pid);
                write(fd, str, strlen(str));
                close(fd);
            }
        }
    }

    return 0;
}

使用gcc编译器进行程序编译

gcc -o process process.c

在这里插入图片描述

运行程序

./process

在这里插入图片描述

1.3. 有爷爷爸爸孙子三人一起工作,前两秒三人一起休息讨论工作,之后爷爷每2秒休息一次,爸爸每4秒休息一次,儿子每6秒休息一次,请按照关系创建父子进程,每人每次休息时都打印他的身份、进程pid以及当前时间,工作时间为18s。

在linux上编写c语言程序process.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>

void print_info(char* role) {
    time_t now;
    time(&now);
    printf("%s, pid: %d, time: %s", role, getpid(), ctime(&now));
}

int main() {
    pid_t grandparent, parent, child;

    grandparent = fork(); // 创建爷爷进程

    if (grandparent < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (grandparent == 0) {
        print_info("Grandparent");
        sleep(2); // 休息两秒,与爸爸和孙子一起讨论工作
        exit(0);
    } else {
        parent = fork(); // 创建爸爸进程

        if (parent < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (parent == 0) {
            print_info("Parent");
            sleep(2); // 休息两秒,与爷爷和孙子一起讨论工作
            int work_time = 18; // 设置工作时间为18while (work_time > 0) {
                print_info("Parent");
                sleep(4); //4秒休息一次
                work_time -= 4; // 更新剩余工作时间
            }
            exit(0);
        } else {
            child = fork(); // 创建孙子进程

            if (child < 0) {
                perror("fork");
                exit(EXIT_FAILURE);
            } else if (child == 0) {
                print_info("Child");
                sleep(2); // 休息两秒,与爷爷和爸爸一起讨论工作
                int work_time = 18; // 设置工作时间为18while (work_time > 0) {
                    print_info("Child");
                    sleep(6); //6秒休息一次
                    work_time -= 6; // 更新剩余工作时间
                }
                exit(0);
            } else {
                // 等待子进程结束
                waitpid(child, NULL, 0);
                waitpid(parent, NULL, 0);
                waitpid(grandparent, NULL, 0);
            }
        }
    }

    return 0;
}

使用gcc编译器进行程序编译

gcc -o process process.c

在这里插入图片描述

运行程序

./process

在这里插入图片描述

1.4. 编写程序让两个子进程交替判断一个范围内的整数是不是素数。运行程序时要输入两个参数,一个是左边界,一个是右边界。比如说判断100到200之间哪些是素数,子进程1判断100是不是素数,子进程2判断101是不是素数,子进程1再判断102是不是素数,子进程2判断103是不是素数…,一直轮流下去。

在linux上编写C语言程序process.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

// 判断一个数是否为素数
int is_prime(int num) {
    if (num <= 1)
        return 0;
    for (int i = 2; i*i <= num; i++) {
        if (num % i == 0)
            return 0;
    }
    return 1;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("请提供正确的参数!\n");
        printf("用法: %s 左边界 右边界\n", argv[0]);
        return 1;
    }

    int left = atoi(argv[1]);
    int right = atoi(argv[2]);

    pid_t child1, child2;
    int next_num = left;

    child1 = fork(); // 创建子进程1

    if (child1 < 0) {
        perror("fork");
        return 1;
    } else if (child1 == 0) {
        // 子进程1负责判断奇数
        while (next_num <= right) {
            if (next_num % 2 == 1 && is_prime(next_num))
                printf("%d 是素数\n", next_num);
            next_num++;
            sleep(1);
        }
        exit(0);
    } else {
        child2 = fork(); // 创建子进程2

        if (child2 < 0) {
            perror("fork");
            return 1;
        } else if (child2 == 0) {
            // 子进程2负责判断偶数
            while (next_num <= right) {
                if (next_num % 2 == 0 && is_prime(next_num))
                    printf("%d 是素数\n", next_num);
                next_num++;
                sleep(1);
            }
            exit(0);
        } else {
            // 等待子进程结束
            waitpid(child1, NULL, 0);
            waitpid(child2, NULL, 0);
        }
    }

    return 0;
}

使用gcc编译器进行程序编译

gcc -std=c99 -o process process.c
编译器默认使用了较旧的 C 语言标准,而在较旧的标准下,不允许在 for 循环中声明变量。可以通过添加 -std=c99 或 -std=gnu99 选项来指定使用 C99 标准。

在这里插入图片描述

运行程序

./process 1 100
解释:输出1和去100之间的素数

在这里插入图片描述

1.5. 仿照讲义中的“系统日志守护进程”例子,写一个守护进程,每隔一段时间获取当前登录用户名,将获取到的信息加上当前时间写入系统日志。

提示:

getlogin()、getenv()函数。

在linux上编写c语言程序daemon.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <time.h>

int main() {
    pid_t pid, sid;
    time_t start_time = time(NULL);  // 记录程序启动时间

    // 创建子进程
    pid = fork();

    // 出错处理
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }

    // 父进程退出
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    // 创建新的会话
    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE);
    }

    // 切换工作目录
    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE);
    }

    // 关闭标准输入、输出和错误流
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // 守护进程主体
    while (1) {
        time_t current_time = time(NULL);
        if (current_time - start_time > 60) {  // 当程序运行时间超过一分钟时退出循环
            break;
        }

        time_t rawtime;
        struct tm *timeinfo;
        char buffer[80];

        time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);

        char *username = getlogin();
        if (username == NULL) {
            username = getenv("USER");
        }

        openlog("MyDaemon", LOG_PID, LOG_USER);
        syslog(LOG_INFO, "Current user: %s, Time: %s", username, buffer);
        closelog();

        sleep(10);  // 每隔10秒执行一次
    }

    exit(EXIT_SUCCESS);
}

使用gcc编译器进行程序编译

gcc -o daemon daemon.c

在这里插入图片描述

运行程序

./daemon
# 查看系统
sudo tail -f /var/log/messages

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“闻起来有股答辩的味道”,答辩到底是什么味?

“闻起来有股答辩的味道”&#xff0c;答辩到底是什么味&#xff1f; 一位名叫“小鸡全家桶”的作者虚构了这样一个学校故事&#xff0c;故事说&#xff0c;由于学生的考试试卷印刷得特别模糊&#xff0c;导致里面的插图根本看不清&#xff0c;学生感到懵逼&#xff0c;监考老…

oracle主机虚拟内存不足导致实例宕机

检查alert日志&#xff0c;发现pga资源分配时报内存不足&#xff1a; 由于pga内存不足&#xff0c;而导致的数据库宕机。 查看操作系统日志&#xff1a; 发现在宕机之前&#xff0c;出现了虚拟内存不足的情况。 检查确认设置的虚拟内存大小为50多G&#xff1a; 按道理不该出现…

从零开始:Spring Boot项目中如何集成并使用Infinispan

一、介绍 Infinispan 其实就是一个分布式缓存和数据网格平台&#xff0c;提供了高度可扩展和高性能数据缓存解决方案。Infinispan可以作为本地缓存或分布式缓存使用&#xff0c;支持事务、查询、处理大数据等功能。简单地说&#xff0c;Infinispan 可以理解为是 MySQL 的内存版…

玩转OpenHarmony智能家居:如何实现开发版“碰一碰”设备控制

一、简介 “碰一碰”设备控制&#xff0c;依托NFC短距通信协议&#xff0c;通过碰一碰的交互方式&#xff0c;将OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;标准系统设备和全场景设备连接起来&#xff0c;解决了应用与设备之间接续慢、传输难的问题&…

浅析智能体开发(第二部分):智能体设计模式和软件架构

大语言模型&#xff08;LLM&#xff09;驱动的智能体&#xff08;AI Agent&#xff09;展现出许多传统软件所不具备的特征。不仅与传统软件的设计理念、方法、工具和技术栈有显著的差异&#xff0c;AI原生&#xff08;AI Native&#xff09;的智能体还融入了多种新概念和技术。…

springboot-阿里羚羊 服务端埋点

官方文档 集成Java SDK 手动引入jar包「quickaplus-log-collector-java-sdk-1.0.1-SNAPSHOT.jar」 <dependency><groupId>com.alibaba.lingyang</groupId><artifactId>quickaplus-log-collector-java-sdk</artifactId><version>1.0.1&l…

心识宇宙 x TapData:如何加速落地实时数仓,助力 AI 企业智慧决策

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量代替 OGG、DSG 等同步工具&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业将真正具有业务价值的数据作用到实处&#xff0c…

Java(十)---抽象类和接口

文章目录 前言知识回顾1.抽象类1.1.抽象类语法1.2 抽象类特性 2.接口2.1.接口的概念2.2 语法规则2.3 接口使用2.4 接口特性2.5 实现多个接口 3.Object类3.1 获取对象信息3.2.对象比较equals方法 4.接口使用实例4.1.Comparable4.2.Comparator4.3.Cloneable深拷贝和浅拷贝 前言 …

CCF-GESP 等级考试 2023年9月认证C++四级真题

2023年9月 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 第 1 题 ⼈们所使⽤的⼿机上安装的App通常指的是&#xff08; &#xff09;。 A. ⼀款操作系统B. ⼀款应⽤软件C. ⼀种通话设备D. 以上都不对 第 2 题 下列流程图的输出结果是&#xff1f;( ) A. 9B.…

2024/5/22 学习杂记

为什么功率放大电路在模电中经常提到&#xff1f; 模拟信号&#xff1a;它是连续变化的电信号&#xff0c;它在时间上和幅度上都是连续的&#xff0c;能够代表信息的连续变化。大多数物理量为模拟信号&#xff0c;如&#xff1a;温度、压力、流量… 非电物理量通过传感器变换成…

RabbitMQ 消息队列安装及入门

市面常见消息队列中间件对比 技术名称吞吐量 /IO/并发时效性&#xff08;类似延迟&#xff09;消息到达时间可用性可靠性优势应用场景activemq万级高高高简单易学中小型企业、项目rabbitmq万级极高&#xff08;微秒&#xff09;高极高生态好&#xff08;基本什么语言都支持&am…

告别付费!这款开源软件让你免费看高清电视直播!

文章目录 📖 介绍 📖🏡 演示环境 🏡📝 开源详情 📝🎯 软件介绍🚀 软件特点🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 🔮 揭秘一款神奇的软件,让你轻松畅游电视直播的海洋,无需付费,无需繁琐设置,即可畅享海量高清节目!想要知道它是什么吗?跟…

如何改变echo在Linux下的输出颜色

文章目录 问题回答常规输出字体加粗斜体字带下划线闪烁效果 参考 问题 我正在尝试使用 echo 命令在终端中打印文本。 我想把文本打印成红色。我该怎么做&#xff1f; 回答 你可以使用 ANSI escape codes 定义控制输出颜色的变量。 ANSI escape codes是一种用于在文本中设置…

Gitee在已有项目基础上创建仓库中遇到的问题和解决

问题一&#xff1a;fatal: remote origin already exists 解释&#xff1a;当前仓库添加了一个名为"origin"的远程仓库配置&#xff0c;此时输入 git remote add origin https://xxx就会提示上面的内容。 解决方案1:移除旧的origin git remote remove origin 解决方案…

pyqt6入门案例

效果预览 hello.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Dialog</class><widget class"QDialog" name"Dialog"><property name"geometry"><…

2024年5月份最新独角数卡使用USDT详细小白教程

直观配套视频教程 2024年5月份最新独角数卡安装及USDT使用详细小白教程 1、创建服务器 Centos或者Ubuntu2、宝塔面板开心版安装寶塔 Linux 面版 8.0.5 開心版 - 2024年1月12日 - 开心专区 - 异次元 - Powered by Discuz!Centos安装命令&#xff08;默认安装是 8.0.1 直接在线升…

PyMySQL:连接Python与MySQL的桥梁

系列文章目录 更新ing... MySQL操作全攻略&#xff1a;库、表、数据、事务全面指南深入探索MySQL SELECT查询&#xff1a;从基础到高级&#xff0c;解锁数据宝藏的密钥MySQL SELECT查询实战&#xff1a;练习题精选&#xff0c;提升你的数据库查询技能PyMySQL&#xff1a;连接P…

代码随想录算法训练营第三十四天 | 理论基础、455.分发饼干、376、摆动序列、53.最大子序和

目录 理论基础 455.分发饼干 思路 代码 376.摆动序列 思路 代码 53.最大子序和 思路 代码 理论基础 代码随想录 455.分发饼干 代码随想录 思路 可以是大饼干优先满足大胃口&#xff0c;也可以是小饼干优先满足小胃口。 代码 class Solution:def findContentChildre…

【深度学习】与【PyTorch实战】

目录 一、深度学习基础 1.1 神经网络简介 1.2 激活函数 1.3 损失函数 1.4 优化算法 二、PyTorch基础 2.1 PyTorch简介 2.2 张量操作 2.3 构建神经网络 2.4训练模型 2.5 模型评估 三、PyTorch实战 3.1 数据加载与预处理 3.2 模型定义与训练 3.3 模型评估与调优 3…

与WAF的“相爱相杀”的RASP

用什么来保护Web应用的安全&#xff1f; 猜想大部分安全从业者都会回答&#xff1a;“WAF&#xff08;Web Application Firewall,应用程序防火墙&#xff09;。”不过RASP&#xff08;Runtime Application Self-Protection&#xff0c;应用运行时自我保护&#xff09;横空出世…