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

目录

前言

一、守护进程

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/nullopen("/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.xdnf.cn/news/146697.html

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

相关文章

EasyExcel的源码流程(导入Excel)

1. 入口 2. EasyExcel类继承了EasyExcelFactory类&#xff0c;EasyExcel自动拥有EasyExcelFactory父类的所有方法&#xff0c;如read()&#xff0c;readSheet()&#xff0c;write()&#xff0c;writerSheet()等等。 3. 进入.read()方法&#xff0c;需要传入三个参数(文件路径…

全流量安全分析之服务器非法外连

服务器非法外连监控的重要性在于保护服务器的安全性和防止被黑客利用&#xff0c;以下是几个重要的理由&#xff1a; 1、发现恶意活动&#xff1a;通过监控服务器的外连流量&#xff0c;可以及时发现是否有未经授权或可疑的连接尝试。这可能包括入侵攻击、数据泄露、恶意软件传…

小白vite+vue3搭建项目整个流程

第一步 查看npm 版本npm -v&#xff0c;npm版本是7&#xff0c;创建项目命令&#xff1a; npm create vitelatest threejsVue -- --template vue第二步 // 进入项目名为threejsVue的项目命令 cd threejsVue // 安装路由 npm install vue-router4 // 安装css npm install -D s…

手机号码格式校验:@Phone(自定义参数校验注解)

需求 新增接口 和 修改接口 中&#xff0c;手机号码的格式校验是普遍需要的。 在每个手机号码字段上添加正则表达式校验注解来实现校验&#xff0c;重复书写&#xff0c;容易出错&#xff1b;在不同的手机号码字段上&#xff0c;可能使用了不同的校验规则&#xff0c;无法有效…

【单片机】14-I2C通信之EEPROM

1.EEPROM概念 1.EEPROM 1.1 一些概念 &#xff08;1&#xff09;一些概念&#xff1a;ROM【只读存储器---硬盘】&#xff0c;RAM【随机访问存储器--内存】&#xff0c;PROM【可编程的ROM】&#xff0c;EPROM【可擦除ROM】&#xff0c;EEPROM【电可擦除ROM】 1.2 为什么需要EE…

gitlab配置webhook限制提交注释

一、打开gitlab相关配置项 vim /etc/gitlab/gitlab.rb gitlab_shell[custom_hooks_dir] "/etc/gitlab/custom_hooks" 二、创建相关文件夹 mkdir -p /etc/gitlab/custom_hooks mkdir -p /etc/gitlab/custom_hooks/post-receive.d mkdir -p /etc/gitlab/custom_h…

xcode15下载ios17模拟器失败

升级到xcode15后需要安装ios17模拟器 但是在下载过程中会遇到报错 如下图这种 网上搜索了一下发现有人遇到过无法下载的问题&#xff0c;并且在apple官网也有人提出类似问题 https://developer.apple.com/forums/thread/737648 解决方案就是从https://developer.apple.com/do…

Halcon中灰度直方图的使用与学习

目录 第一步:当前打开窗口的显示灰度图或者mono图片第二步:激活后,我们可以去调整调整右边直方图灰阶值的中蓝色和红色竖线,获取左边图上的灰阶值的范围内的特征显示。第三步:插入代码:总结:它的直观目的,就是查看灰度的分布情况!灰度直方图,是我们经常使用,抓取不同…

Mendix中的依赖管理:npm和Maven的应用

序言 在传统java开发项目中&#xff0c;我们可以利用maven来管理jar包依赖&#xff0c;但在mendix项目开发Custom Java Action时&#xff0c;由于目录结构有一些差异&#xff0c;我们需要自行配置。同样的&#xff0c;在mendix项目开发Custom JavaScript Action时&#xff0c;…

HBase高阶(一)基础架构及存储原理

一、HBase介绍 简介 HBase是Hadoop生态系统中的一个分布式、面向列的开源数据库&#xff0c;具有高可伸缩性、高性能和强大的数据处理能力。广泛应用于处理大规模数据集。 HBase是一种稀疏的、分布式、持久的多维排序map 稀疏&#xff1a;对比关系型数据库和非关系型数据库&a…

【软件工程_UML—StartUML作图工具】startUML怎么画interface接口

StartUML作图工具怎么画interface接口 初试为圆形 &#xff0c;点击该接口在右下角的设置中->Format->Stereotype Display->Label&#xff0c;即可切换到想要的样式 其他方式 在class diagram下&#xff0c;左侧有interface图标&#xff0c;先鼠标左键选择&#xff0…

MNIST手写数字识别

MNIST是一个手写体数字的图片数据集&#xff0c;该数据集由美国国家标准与技术研究所&#xff08;National Institute of Standards and Technology (NIST)&#xff09;发起整理&#xff0c;其包含 60,000 张训练图像和 10,000 张测试图像&#xff0c;每张图片的尺寸为 28 x 28…

Explain执行计划字段解释说明---ID字段说明

ID字段说明 1、select查询的序列号,包含一组数字&#xff0c;表示查询中执行select子句或操作表的顺序 2、ID的三种情况 &#xff08;1&#xff09;id相同&#xff0c;执行顺序由上至下。 &#xff08;2&#xff09;id不同&#xff0c;如果是子查询&#xff0c;id的序号会…

NEON优化:性能优化经验总结

NEON优化&#xff1a;性能优化经验总结 1. 什么是 NEONArm Adv SIMD 历史 2. 寄存器3. NEON 命名方式4. 优化技巧5. 优化 NEON 代码(Armv7-A内容&#xff0c;但区别不大)5.1 优化 NEON 汇编代码5.1.1 Cortex-A 处理器之间的 NEON 管道差异5.1.2 内存访问优化 Reference: NEON优…

大数据Flink(九十四):DML:TopN 子句

文章目录 DML:TopN 子句 DML:TopN 子句 TopN 定义(支持 Batch\Streaming):TopN 其实就是对应到离线数仓中的 row_number(),可以使用 row_number() 对某一个分组的数据进行排序 应用场景

APP或小程序突然打开显示连接网络失败,内容一片空白的原因是,SSL证书到期啦,续签即可

由于我们使用的是https&#xff0c;所以SSL证书到期了&#xff0c;通过https进入读取内容的APP或网站或小程序就会打开后连接网络失败&#xff0c;出现空白&#xff0c;这是因为我们申请的SSL证书到期了&#xff0c;因为我们申请的证书有效期有时是1个月或3个月&#xff0c;到期…

BI神器Power Query(26)-- 使用PQ实现表格多列转换(2/3)

实例需求&#xff1a;原始表格包含多列属性数据,现在需要将不同属性分列展示在不同的行中&#xff0c;att1、att3、att5为一组&#xff0c;att2、att3、att6为另一组&#xff0c;数据如下所示。 更新表格数据 原始数据表&#xff1a; Col1Col2Att1Att2Att3Att4Att5Att6AAADD…

【AI视野·今日NLP 自然语言处理论文速览 第四十二期】Wed, 27 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 27 Sep 2023 Totally 50 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Attention Satisfies: A Constraint-Satisfaction Lens on Factual Errors of Language Models Authors Mert …

Flutter开发之Package与Plugin

前言 在flutter中有包和插件两个概念&#xff0c;插件 (plugin) 是 package 的一种&#xff0c;全称是 plugin package&#xff0c;我们简称为 plugin&#xff0c;中文叫插件。包(Package)主要指对flutter相关功能的封装&#xff0c;类似于Android中的插件和iOS中的三方库。而插…

JVM机制理解与调优方案

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有需要我的支持&#xff0c;请私信或评论留言&#xff01; 前言 很多Java开发…