C/C++进程超详细详解【中部分】(系统性学习day07)

news2024/11/29 10:47:27

目录

前言

一、守护进程

1.概念

2.守护进程创建的原理(如图清晰可见)

 3.守护进程的实现(代码块)

二、dup和dup2

1,复制文件描述符

2.文件描述符重定向

三、系统日志

1,打开日志

2,向日志中写消息

3,关闭日志

四,文件锁

1.概念

2,给整个文件上锁

实例代码如下: 

3,给文件的某个区域上锁

 实例代码如下:

五,进程间通信

1.分类

2,无名管道

2.1 无名管道通信原理

2.2 用法

 实例代码如下:

总结


前言

上篇博客对C/C++进程的上部分进行了详细讲解,本篇博客将继续讲解和补充关于线程的知识点。


一、守护进程

1.概念

(1)守护进程,
    也就是通常所说的Daemon进程,是Linux中的后台服务进程。
    它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件
    守护进程常常在系统引导装入时启动,在系统关闭时终止
    Linux系统有很多守护进程,大多数服务都是用守护进程实现的 

(2)终端
    在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会被自动关闭。

守护进程能够突破这种限制,它从被执行开始运转,直到整个系统关闭才会退出。
如果想让某个进程不因为用户或终端或其他的变化而受到影响,就必须把这个进程变成一个守护进程。 

2.守护进程创建的原理(如图清晰可见)

 

 3.守护进程的实现(代码块)

void init_deamon(void)
{
    /*************** start ****************************/
    pid_t pid;
    int i,max_fd;

    //1,创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(pid > 0)
        exit(0);

    //2,创建新会话
    if(setsid() < 0){
        perror("setsid");
        exit(1);
    }
    //3,再创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(pid > 0)
        exit(0);

    //4,修改守护进程的工作目录
    chdir("/");

    //5,关闭进程父进程的所有的文件描述符
    max_fd = sysconf(_SC_OPEN_MAX);
    for (i = 0; i < max_fd;i++)
        close(i);
    //6,将标准输入,标准输出和标准错误重定向到/dev/null
    open("/dev/null",O_RDWR);
    dup(0);
    dup(0);

    //7,消除umask影响
    umask(0);
    /*************** end ****************************/
}

二、dup和dup2

1,复制文件描述符

int dup(int oldfd);
//参数 ---- 要复制的文件描述符
//返回值 ----成功:新的文件描述符,失败:-1

例如: 
int main(void)
{
    char str[] = "hello world";
    int fd1,fd2;


    fd1 = open("1.txt",O_RDWR|O_CREAT,0666);
    if(fd1 < 0){
        perror("open");
        exit(1);
    }

    write(fd1,str,strlen(str));

    fd2 = dup(fd1);   //复制文件描述fd1
    strcpy(str,"farsight");
    write(fd2,str,strlen(str));

    close(fd1);


    return 0;
}      
 

2.文件描述符重定向

int dup2(int oldfd, int newfd);
//参数1 --- 目标文件描述符
//参数2 --- 要重定向的文件描述符
//返回值 ---- 成功0,失败:-1

例如: 
int main(void)
{
    char str[] = "hello world";
    int fd1,fd2;


    fd1 = open("1.txt",O_RDWR|O_CREAT,0666);
    if(fd1 < 0){
        perror("open");
        exit(1);
    }
    fd2 = open("2.txt",O_RDWR|O_CREAT,0666);
    if(fd1 < 0){
        perror("open");
        exit(1);
    }

    write(fd1,str,strlen(str));

    dup2(fd1,fd2);  //将fd2重定向到fd1

    strcpy(str,"farsight");
    write(fd2,str,strlen(str));
    close(fd1);


    return 0;
}

三、系统日志

1,打开日志

#include <syslog.h>
void openlog(const char *ident, int option, int facility);
//参数1 ------  //日志标签,自定义,方便查找日志信息
//参数2 ------  选项:
                LOG_CONS     如果消息不能发送给日志,则发送到控制台
                LOG_NDELAY   不延迟打开套接字,并发送消息
                LOG_NOWAIT   创建子进程,不阻塞发送消息给日志
                LOG_PERROR   发送日志,同时发送到标准错误文件
                LOG_PID      在消息中加入进程的ID
//参数3 ------   进程类型:
                    LOG_DAEMON      守护进程
                    LOG_FTP          tfp服务进程
                    LOG_KERN      内核进程
                    LOG_LPR       打印服务进程
                    LOG_MAIL      邮件服务进程

实例如下:
    openlog("mydaemon",LOG_PID,LOG_DAEMON);

2,向日志中写消息

void syslog(int priority, const char *format, ...);
//参数1 ----- 消息的优先级
               LOG_EMERG      非常紧急的错误
               LOG_ALERT      必须马上处理的错误
               LOG_CRIT       关键性错误
               LOG_ERR        一般错误
               LOG_WARNING    警告
               LOG_NOTICE     需要注意的消息
               LOG_INFO       正常消息
               LOG_DEBUG      调试消息
//参数2 -----向日志中写消息的格式
//变参 ----- 类似于printf的变参
例如: 
    syslog(LOG_ERR,"fopen:%s",strerror(errno));
    
运行测试:
     grep mydaemon /var/log/syslog -n
    203:Sep 26 23:36:26 ubuntu mydaemon[28968]: fopen:No such file or directory

3,关闭日志

 void closelog(void);

四,文件锁

1.概念

为了解决进程之间的互斥问题,引入咨询锁

采用锁文件的方式取代创建文件的方式
    需遵循“君子协定”
    共享锁(shared Lock)和互斥锁(exculusive lock)
    对整个文件上锁或者文件的某个部分上锁(记录锁定)

2,给整个文件上锁

#include <sys/file.h>
int flock(int fd, int operation);
//参数1 ---- 文件描述符
//参数2 ---- 锁的类型:LOCK_SH  LOCK_EX  LOCK_UN
//返回值 ---成功:0,失败:-1

实例代码如下: 

代码一:

int main(int argc,char **argv)
{
    int fd;
    int i;

    if(argc != 2){
        fprintf(stderr,"Usage: %s <filename>\n",argv[0]);
        exit(0);
    }

    if((fd = open(argv[1],O_RDWR)) < 0){
        perror("open");
        exit(1);
    }

    while(1){
        printf("等待获取锁\n");
        //获取互斥锁
        if(flock(fd,LOCK_EX) < 0){
            perror("flock");
            exit(1);
        }

        for(i = 0; i < 7; i++){
            printf("正在上厕所\n");
            sleep(1);
        }
        //释放锁
        if(flock(fd,LOCK_UN) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所出来了....\n");
        sleep(1);
    }
    return 0;
}
 

代码二:

int main(int argc,char **argv)
{
    int fd;
    int i;

    if(argc != 2){
        fprintf(stderr,"Usage: %s <filename>\n",argv[0]);
        exit(0);
    }

    if((fd = open(argv[1],O_RDWR)) < 0){
        perror("open");
        exit(1);
    }

    while(1){
        printf("等待着上厕所\n");
        //获取互斥锁
        if(flock(fd,LOCK_EX) < 0){
            perror("flock");
            exit(1);
        }
        for(i = 0; i < 7; i++){
            printf("正在上厕所...\n");
            sleep(1);
        }
        //释放锁
        if(flock(fd,LOCK_UN) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所!\n");
        sleep(1);
    }
    return 0;
}

3,给文件的某个区域上锁

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

 struct flock {
       short l_type;    /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */
       short l_whence;  /* How to interpret l_start:
                           SEEK_SET, SEEK_CUR, SEEK_END */
       off_t l_start;   /* Starting offset for lock */
       off_t l_len;     /* Number of bytes to lock */
       pid_t l_pid;     /* PID of process blocking our lock
                           (set by F_GETLK and F_OFD_GETLK) */
   };

 实例代码如下:

//定义锁的结构体--设置锁的区域
     struct flock fl = {
         .l_whence = SEEK_SET,
        .l_start = 100,
        .l_len  = 1024,
    };

    while(1){
        printf("等待获取锁\n");
        //获取互斥锁
        fl.l_type = F_WRLCK;   //设置锁的类型
        if(fcntl(fd,F_SETLKW,&fl) < 0){
            perror("flock");
            exit(1);
        }

        for(i = 0; i < 7; i++){
            printf("正在上厕所\n");
            sleep(1);
        }
        //释放锁
        fl.l_type = F_UNLCK;    //解锁
        if(fcntl(fd,F_SETLK,&fl) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所出来了....\n");
        sleep(1);
    }

五,进程间通信

1.分类

 在linux中进程间通信分为三类:
(1)早期的进程间通信
    无名管道
    有名(命名)管道
    信号
(2)system V IPC
    消息队列
    共享内存
    信号灯(量)
(3)unix域套接字

2,无名管道

2.1 无名管道通信原理

2.2 用法

#include <unistd.h>
int pipe(int pipefd[2]);
//参数 ---- 保存管道两端文件描述符的数组
//返回值 ---成功:0,失败:-1

 实例代码如下:
int main(void)
{
    int fd[2];
    pid_t pid;
    char buf[100];

    //创建无名管道
    if(pipe(fd) < 0){   //pipe()会在内核中创建无名管道,然后将管道两端的文件描述符返回给当前进程
        perror("pipe");
        exit(1);
    }

    //创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(!pid){  //子进程执行:从键盘获取字符串,写到管道中
        close(fd[0]);  //关闭读端
        while(1){
            fgets(buf,sizeof(buf),stdin);
            write(fd[1],buf,strlen(buf));   //向管道中写数据
        }
    }else{  //父进程执行:从管道读数据,打印到屏幕上
        close(fd[1]); //关闭写端
        while(1){
           if(read(fd[0],buf,sizeof(buf)) < 0){
                perror("read");
                exit(1);
           }
           printf("%s",buf);
        }
    }

    return 0;
}


总结

        本篇文章针对进程进行超详细讲解和补充,希望能够帮到大家!

        以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识,感谢大家支持懒大王!

       希望这篇博客能给各位朋友们带来帮助,最后懒大王请来过的朋友们留下你们宝贵的三连以及关注,感谢你们!

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

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

相关文章

【MATLAB】字体美化和乱码

文章目录 前言首先说说说字体美化乱码到底是怎么导致的&#xff1f;1 字体导致的乱码2 编码导致的乱码总结 前言 最近打开MATLAB&#xff0c;又发现了一个问题&#xff1a;编辑器中的中文输入在命令行或者说终端输出竟然是乱码&#xff0c;然后赶紧翻阅了一下此前的博客以及未发…

基于Java的校园资料分享平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理①

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理 第十八章 Linux 系统对中断的处理①18.1 进程、线程、中断的核心&#xff1a;栈18.1.1 ARM 处理器程序运行的过程18.1.2 程序被中断时&#xff0c;怎么保存现场18.1.3 进程、线程的概念 18.2 Linux系统对中断处理的演进…

Python实用技术二:数据分析和可视化(2)

目录 一&#xff0c;多维数组库numpy 1&#xff0c;操作函数&#xff1a;​ 2&#xff0c;numpy数组元素增删 1&#xff09;添加数组元素 2&#xff09;numpy删除数组元素 3&#xff09;在numpy数组中查找元素 4&#xff09;numpy数组的数学运算 3&#xff0c;numpy数…

windows系统利用powershell查看系统支持那些Windows功能选项

在PowerShell中&#xff0c;我们可以使用Get-WindowsOptionalFeature cmdlet命令来查看Windows功能选项。 打开PowerShell 输入以下命令&#xff1a;将结果输出到1.log Get-WindowsOptionalFeature -Online >1.log 可以看到在指定路径下看到生成了文件 打开查看内容&…

Linux基础指令(六)

目录 前言1. man 指令2. date 指令3. cal 指令4. bc 指令5. uname 指令结语&#xff1a; 前言 欢迎各位伙伴来到学习 Linux 指令的 第六天&#xff01;&#xff01;&#xff01; 在上一篇文章 Linux基本指令(五) 中&#xff0c;我们通过一段故事线&#xff0c;带大家感性的了…

数学建模Matlab之优化类方法

本文还是来源于http://t.csdnimg.cn/P5zOD&#xff0c;但肯定不可能只有这些内容&#xff0c;否则那位作者应该会打我……&#xff0c;在这里&#xff0c;只是讲解优化类问题比较常用的方法&#xff0c;以TSP问题为例&#xff0c;适合入门。 模拟退火 模拟退火是一种概率算法&a…

软件设计师_数据库系统_学习笔记

文章目录 3.1 数据库模式3.1.1 三级模式 两级映射3.1.2 数据库设计过程 3.2 ER模型3.3 关系代数与元组演算3.4 规范化理论3.5 并发控制3.6 数据库完整性约束3.7 分布式数据库3.8 数据仓库与数据挖掘 3.1 数据库模式 3.1.1 三级模式 两级映射 内模式直接与物理数据库相关联的 定…

PWN Test_your_nc Write UP

目录 PWN 00 解题过程 总结归纳 PWN 01 解题过程 总结归纳 PWN 02 解题过程 总结归纳 PWN 03 解题过程 总结归纳 PWN 04 解题过程 总结归纳 CTF PWN 开始&#xff01; 冲就完了 PWN 00 解题过程 ssh远程链连接 ssh ctfshowpwn.challenge.ctf.show -p28151 输…

Git使用【上】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析3 前言 先前有些git命令我在我的其它文章里面已经写过&#xff0c;若要查看可参考【Linu…

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理②

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理② 第十八章 Linux系统对中断的处理 ②18.3 Linux中断系统中的重要数据结构18.3.1 irq_desc数组18.3.2 irqaction结构体18.3.3 irq_data结构体18.3.4 irq_domain结构体18.3.5 irq_chip结构体 18.4 在设备树中指定中断_在…

【Python】返回指定时间对应的时间戳

使用模块datetime&#xff0c;附赠一个没啥用的“时间推算”功能(获取n天后对应的时间 代码&#xff1a; import datetimedef GetTimestamp(year,month,day,hour,minute,second,*,relativeNone,timezoneNone):#返回指定时间戳。指定relative时进行时间推算"""根…

前端开发网站推荐

每个人都会遇见那么一个人&#xff0c;永远无法忘却&#xff0c;也永远不能拥有。 以下是一些可以用来查找和比较前端框架的推荐网站&#xff1a; JavaScript框架比较&#xff1a; 这些网站提供了对不同JavaScript框架和库的详细比较和评估。 JavaScripting: 提供了大量的JavaS…

深入了解 Linux 中的 AWK 命令:文本处理的瑞士军刀

简介 在Linux和Unix操作系统中&#xff0c;文本处理是一个常见的任务。AWK命令是一个强大的文本处理工具&#xff0c;专门进行文本截取和分析&#xff0c;它允许你在文本文件中查找、过滤、处理和格式化数据。本文将深入介绍Linux中的AWK命令&#xff0c;让你了解其基本用法和…

Cesium实现动态旋转四棱锥(2023.9.11)

Cesium实现动态悬浮旋转四棱锥效果 2023.9.11 1、引言2、两种实现思路介绍2.1 思路一&#xff1a;添加已有的四棱锥&#xff08;金字塔&#xff09;模型实现&#xff08;简单但受限&#xff09;2.2 思路二&#xff1a;自定义四棱锥几何模型实现&#xff08;复杂且灵活&#xff…

双指针算法——复写零

双指针算法——复写零&#x1f60e; 前言&#x1f64c;复写零板书分析&#xff1a;解题代码&#xff1a;B站视频讲解 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&#xff1a;全神贯注的上吧&#xff01;&#xff01;&#…

VUE3照本宣科——认识VUE3

VUE3照本宣科——认识VUE3 前言一、命令创建项目1.中文官网2.菜鸟教程 二、VUE3项目目录结构1.public2.src&#xff08;1&#xff09;assets&#xff08;2&#xff09;components 3. .eslintrc.cjs4. .gitignore5. .prettierrc.json6.index.html7.package.json8.README.md9.vit…

芒果叶病害数据集(用于图像分类,每类500张照片)

1.数据集介绍 数据类型&#xff1a;240x320 像素的芒果叶图像。数据格式&#xff1a;JPG。图像数量&#xff1a;共有4000张图像。其中约有1800张是不同的叶子图像&#xff0c;其余的是通过缩放和旋转进行制备的。考虑的病害&#xff1a;包括七种病害&#xff0c;分别是炭疽病、…

大型项目开发设计文档规范

目录 一、 需求文档分析 二、 需求分析 1.交互层分析 2.功能需求分析 3.数据分析 4.兼容性分析 5.非功能性分析 三、 系统现状分析 1. 判断要开发的功能属于哪个模块&#xff0c;需要与哪几个模块联动&#xff1f; 2. 要开发的功能属于新接口开发&#xff0c;还是既有…

下载安装 VMware 虚拟机

文章目录 基本介绍下载并安装 VMware Workstation创建虚拟机iso镜像下载地址开始系统安装配置选择语言ip和代理盘符和用户及密码远程github软件安装开始安装重启使用 安装 VMware Tools 基本介绍 VMware 是什么&#xff1f;虚拟机是什么&#xff1f;二者有什么关系&#xff1f;…