Linux学习笔记(应用篇一)

基于I.MX6ULL.MINI开发板

  • 标准I/O库
  • 链接
  • 目录
  • 删除文件
  • 正则表达式
  • 系统标识
  • 时间
  • 堆内存
  • 信号
    • 标准信号
  • 进程
  • 进程组
  • 进程间通信
  • 线程
    • 互斥锁
    • 线程安全

本文章是入门篇的概念,有点零散,后续需要补充复习

**inode(索引节点)**是 Linux 和 Unix 文件系统(如ext4、xfs)中的数据结构,用于存储文件的元信息(metadata),而不存储文件内容或文件名。
inode 存储的信息
文件类型(普通文件、目录、符号链接等)
文件权限(rwx)
所有者(UID)和组(GID)
文件大小
创建、修改、访问时间(ctime、mtime、atime)
链接计数(有多少硬链接指向这个文件)
数据块指针(指向文件数据所在的磁盘块)
inode 不包含的信息
文件名:文件名存储在目录(dirent 结构)中,并通过 inode 号与 inode 关联。

在测试函数strerror
用命令gcc -o test test.c编译下面的代码时报错

[/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/14/…/…/…/x86_64-linux-gnu/Scrt1.o: in function ’_start‘: (.text+0x1b): undefined reference to `main’collect2: error: ld returned 1 exit status

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>int main(void)
{int fd;/* 打开文件 */fd = open("./test_file", O_RDONLY);if (-1 == fd) {printf("Error: %s\n", strerror(errno));return -1;}close(fd);return 0;
}

原因是没有使用共享库
使用命令gcc -shared -g -o test test.c就能编译成功了

命令du -h 文件名,可以查看文件实际占用存储块的大小

函数menset,给数组赋值

void *memset(void *str, int c, size_t n)

同一个进程中多次调用 open 函数打开同一个文件,各数据结构之间的关系如下图所示
在这里插入图片描述

不同进程中分别使用 open 函数打开同一个文件,其数据结构关系图如下所示:
在这里插入图片描述

同一个进程中通过 dup(dup2)函数对文件描述符进行复制,其数据结构关系如下图所示:

在这里插入图片描述

标准I/O库

函数FILE *fopen(const char *path, const char *mode);
参数mode取值如下

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

定义一个用于存放数据的 buf,起始地址以 4096 字节进行对齐
static char buf[8192] __attribute((aligned (4096)));

__attribute 是 gcc 支持的一种机制(也可以写成__attribute __) ,可用于设置函数属性、变量属性以及类型属性等

fd = open("./test_file", O_WRONLY | O_CREAT | O_TRUNC, 0664);

0664 是文件权限(mode),用于指定新创建文件的访问权限。在 open() 调用中,它只有在 O_CREAT 标志存在时才生效。

在这里插入图片描述

查看文件类型方法
命令statls
stat可以看到很详细的信息
ls -l通过符号表示文件的类型
在这里插入图片描述

Linux 系统中,可将硬件设备分为字符设备和块设备,所以就有了字符设备文件和块设备文件两种文件类型。虽然有设备文件,但是设备文件并不对应磁盘上的一个文件,也就是说设备文件并不存在于磁盘中,而是由文件系统虚拟出来的,一般是由内存来维护,当系统关机时,设备文件都会消失;字符设备文件一般存放在Linux 系统/dev/目录下,所以 /dev 也称为虚拟文件系统 devfs

Ubuntu 发行版对 ls 命令做了别名处理,执行 ls命令的时候携带了一些选项,而这些选项会访问文件的一些信息,所以导致出现"权限不够"问题,这也说明,只拥有读权限、是没法访问目录下的文件的;为了确保使用的是ls 命令本身,执行时需要给出路径的完整路径/bin/ls

链接

硬链接:ln 源文件 链接文件
软链接:ln -s 源文件 链接文件

硬链接:int link(const char *oldpath, const char *newpath);
软链接:int symlink(const char *target, const char *linkpath);

取出软链接文件中存储的路径信息:ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);

目录

创建目录:int mkdir(const char *pathname, mode_t mode);
删除目录:int rmdir(const char *pathname);
打开目录:DIR *opendir(const char *name);
读取目录:struct dirent *readdir(DIR *dirp);void rewinddir(DIR *dirp);
关闭目录:int closedir(DIR *dirp);

获取进程当前的工作目录:char *getcwd(char *buf, size_t size);
修改当前的工作目录:int chdir(const char *path);int fchdir(int fd);

删除文件

系统调用:uint unlink(const char *pathname);
C库函数:int remove(const char *pathname);

正则表达式

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>
int main(int argc, char *argv[])
{regmatch_t pmatch = {0};regex_t reg;char errbuf[64];int ret;char *sptr;int length;int nmatch; //最多匹配出的结果/*作用:检查命令行参数数量是否正确(应有 3 个参数)。argv[1]:正则表达式argv[2]:待匹配字符串argv[3]:最大匹配次数如果参数不符合要求,程序退出。*/if (4 != argc) {/*********************************** 执行程序时需要传入两个参数:* arg1: 正则表达式* arg2: 待测试的字符串* arg3: 最多匹配出多少个结果**********************************/fprintf(stderr, "usage: %s <regex> <string> <nmatch>\n", argv[0]);exit(0);}/* 编译正则表达式regcomp(&reg, argv[1], REG_EXTENDED) 编译正则表达式如果编译失败,使用 regerror() 输出错误信息,并退出。*/if(ret = regcomp(&reg, argv[1], REG_EXTENDED)) {regerror(ret, &reg, errbuf, sizeof(errbuf));fprintf(stderr, "regcomp error: %s\n", errbuf);exit(0);}/* 赋值操作sptr 指向待匹配的字符串length 记录 sptr 长度nmatch 由 argv[3] 转换为整数,代表最多匹配多少次*/sptr = argv[2]; //待测试的字符串length = strlen(argv[2]);//获取字符串长度nmatch = atoi(argv[3]); //获取最大匹配数/* 匹配正则表达式循环 nmatch 次,每次尝试匹配正则regexec(&reg, sptr, 1, &pmatch, 0) 执行正则匹配pmatch.rm_so:匹配子串的起始位置pmatch.rm_eo:匹配子串的结束位置如果 regexec() 失败(无匹配),打印错误并跳转到 out 释放正则资源。*/for (int j = 0; j < nmatch; j++) {char temp_str[100];/* 调用 regexec 匹配正则表达式 */if(ret = regexec(&reg, sptr, 1, &pmatch, 0)) {regerror(ret, &reg, errbuf, sizeof(errbuf));fprintf(stderr, "regexec error: %s\n", errbuf);goto out;}if(-1 != pmatch.rm_so) {//pmatch.rm_so == pmatch.rm_eo 时,匹配的是 空字符串,需要跳过 1 个字符,防止死循环。if (pmatch.rm_so == pmatch.rm_eo) {//空字符串sptr += 1;length -= 1;printf("\n"); //打印出空字符串if (0 >= length)//如果已经移动到字符串末尾、则退出break;continue; //从 for 循环开始执行}//memcpy() 提取 sptr 中匹配的子串,并存入 temp_str//printf("%s\n", temp_str); 打印匹配结果memset(temp_str, 0x00, sizeof(temp_str));//清零缓冲区memcpy(temp_str, sptr + pmatch.rm_so,pmatch.rm_eo - pmatch.rm_so);//将匹配出来的子字符串拷贝到缓冲区printf("%s\n", temp_str); //打印字符串//跳过当前匹配的部分,继续匹配剩余字符串//避免死循环(如果 length <= 0,停止匹配)sptr += pmatch.rm_eo;length -= pmatch.rm_eo;if (0 >= length)break;}}/* 释放正则表达式 */
out:regfree(&reg);exit(0);}
./regex_program "a[0-9]+" "abc a12 b34 a56 a78 xyz" 3 //代码执行
//匹配 a 后跟随 至少一个数字
//只匹配 最多 3 次(nmatch=3)
/*
结果
a12
a56
a78
*/

系统标识

struct utsname {char sysname[]; /* 当前操作系统的名称 */char nodename[]; /* 网络上的名称(主机名) */char release[]; /* 操作系统内核版本 */char version[]; /* 操作系统发行版本 */char machine[]; /* 硬件架构类型 */#ifdef _GNU_SOURCEchar domainname[];/* 当前域名 */#endif
};
struct sysinfo {long uptime; /* 自系统启动之后所经过的时间(以秒为单位) */unsigned long loads[3]; /* 1, 5, and 15 minute load averages */unsigned long totalram; /* 总的可用内存大小 */unsigned long freeram; /* 还未被使用的内存大小 */unsigned long sharedram; /* Amount of shared memory */unsigned long bufferram; /* Memory used by buffers */unsigned long totalswap; /* Total swap space size */unsigned long freeswap; /* swap space still available */unsigned short procs; /* 系统当前进程数量 */unsigned long totalhigh; /* Total high memory size */unsigned long freehigh; /* Available high memory size */unsigned int mem_unit; /* 内存单元大小(以字节为单位) */char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};

时间

GMT 时间
GMT(Greenwich Mean Time)中文全称是格林威治标准时间,这个时间系统的概念在 1884 年被确立,由英国伦敦的格林威治皇家天文台计算并维护,并在之后的几十年向欧陆其它国家扩散。
由于从 19 实际开始,因为世界各国往来频繁,而欧洲大陆、美洲大陆以及亚洲大陆都有各自的时区,所以为了避免时间混乱,1884 年,各国代表在美国华盛顿召开国际大会,通过协议选出英国伦敦的格林威治作为全球时间的中心点,决定以通过格林威治的子午线作为划分东西两半球的经线零度线(本初子午线、零度经线),由此格林威治标准时间因而诞生!
所以 GMT 时间就是英国格林威治当地时间,也就是零时区(中时区)所在时间,譬如 GMT 12:00 就是指英国伦敦的格林威治皇家天文台当地的中午 12:00,与我国的标准时间北京时间(东八区)相差 8 个小时,即早八个小时,所以 GMT 12:00 对应的北京时间是 20:00。

UTC 时间
UTC(Coordinated Universal Time)指的是世界协调时间(又称世界标准时间、世界统一时间),是经过平均太阳时(以格林威治时间 GMT 为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC 比 GMT 来得更加精准

查看UTC时间:date -u

jiffies 是内核中定义的一个全局变量,内核使用 jiffies 来记录系统从启动以来的系统节拍数,所以这个变量用来记录以系统节拍时间为单位的时间长度,Linux 内核在编译配置时定义了一个节拍时间,使用节拍率(一秒钟多少个节拍数)来表示

在这里插入图片描述

堆内存

申请堆内存有malloc()calloc()

#define MALLOC_MEM_SIZE (1 * 1024 * 1024)
int main(int argc, char *argv[])
{//声明一个字符指针 base,并初始化为 NULLchar *base = NULL;/* 申请堆内存 *///malloc(MALLOC_MEM_SIZE) 从堆上申请 MALLOC_MEM_SIZE 字节的内存。//malloc() 返回 void* 指针,需要强制转换为 char*base = (char *)malloc(MALLOC_MEM_SIZE);if (NULL == base) {printf("malloc error\n");exit(-1);}/* 初始化申请到的堆内存 */memset(base, 0x0, MALLOC_MEM_SIZE);/* 使用内存 *//* ...... *//* 释放内存 */free(base);return 0}

**calloc()**在堆中动态地分配 nmemb 个长度为 size 的连续空间,并将每一个字节都初始化为 0
calloc()与 malloc()的一个重要区别是:calloc()在动态分配完内存后,自动初始化该内存空间为零,而malloc()不初始化,里边数据是未知的垃圾数据。

一下的两种写法是等价的

// calloc()分配内存空间并初始化
char *buf1 = (char *)calloc(10, 2);// malloc()分配内存空间并用 memset()初始化
char *buf2 = (char *)malloc(10 * 2);
memset(buf2, 0, 20);

信号

标准信号

在这里插入图片描述

核心转储文件(Core Dump)是什么?
核心转储(Core Dump)是 程序崩溃时,操作系统 自动保存的内存快照。它包含了进程在崩溃时的 内存数据、CPU 寄存器、堆栈信息、打开的文件描述符 等信息,帮助开发者 调试程序崩溃的原因。
核心转储文件通常命名为 core 或 core.pid(pid 为进程 ID),默认生成在程序的工作目录。
核心转储文件的作用
1.调试崩溃原因
查看程序崩溃时的调用栈、变量值、内存状态等信息。
2.分析段错误(Segmentation Fault, SIGSEGV)
访问非法地址时,操作系统会触发 SIGSEGV,并生成 core dump。
3.检查死锁、资源泄漏
通过分析核心转储文件,检查线程死锁、文件描述符泄漏等问题。
4.重现难以复现的 Bug
记录程序崩溃时的完整状态,方便后续分析。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

忽略信号(Ignore Signal)
进程接收到信号后,可以选择不处理,相当于信号被丢弃。

捕获信号(Catch Signal)
进程可以定义自定义信号处理函数,在收到信号时执行特定操作,而不是采用默认行为。

进程

在这里插入图片描述

进程组

setpgid(0,pgid) == setpgid(getpgrp(),pgid)
setpgid(pid,0) == setpgid(pid,pid)
setpgrp() == setpgid(0.0) == etpgid(getpgrp(),getpgrp())

./testapp & 中的 & 用于 将命令放入后台运行,使其在 后台执行,而不阻塞当前终端。
输出示例:[1] 12345
[1]: 作业编号(Job ID),可以用 jobs 命令查看。
12345:进程 ID(PID),可以用 kill 12345 终止该进程。

进程间通信

在这里插入图片描述

UNIX 是一种 多用户、多任务 的 操作系统,最早由 AT&T 贝尔实验室 在 1969 年开发。它广泛应用于服务器、工作站和嵌入式系统,以 稳定性、高效性和安全性 著称。

管道: 把一个进程连接到另一个进程的数据流称为管道,管道(Pipe)是一种进程间通信(IPC,Inter-Process Communication) 机制,允许一个进程的输出作为另一个进程的输入,常用于数据流式处理。

在这里插入图片描述

线程

线程处于分离状态(Detached State)意味着该线程的 资源在结束时会自动释放,而 不需要其他线程(如主线程)显式 join() 等待它结束。

互斥锁

Mutex(互斥锁) 是一种线程同步机制,用于防止多个线程同时访问共享资源,避免数据竞争和不一致。

在这里插入图片描述

在这里插入图片描述

执行流(Execution Flow)指的是 程序运行时指令的执行顺序,即 代码如何被逐步执行。它决定了程序如何处理 函数调用、条件判断、循环和多线程等,一个线程就是一条执行流

线程安全

在这里插入图片描述

信号处理函数的执行流(Signal Handling Execution Flow)
在 UNIX/Linux 系统中,信号(Signal)是一种 异步事件,可以在 程序执行的任何时刻打断正常的执行流,然后跳转到 信号处理函数(Signal Handler) 执行特定操作。

//pthread_create() 用于创建一个新线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Modbus RTU ---> Modbus TCP透传技术实现(Modbus透传、RS485透传、RTU透传)分站代码实现、协议转换器

文章目录 Modbus RTU到Modbus TCP透传技术实现1. 透传技术概述1.1 透传基本原理- 协议帧格式转换- 地址映射与管理- 通信时序适配- 错误检测与处理 2. 透传网关硬件架构2.1 典型硬件结构- 微控制器/处理器(ARM、STM32等)- RS-485/RS-232收发器- 以太网控制器(如W5500)- 电源管理…

MySQL数据库中常用的命令

登录&#xff1a; mysql -u username -h ip地址 -P 端口 -p 密码 mysql -u username -S /path/mysql.sock -P -p 用户管理&#xff1a; select user,host from mysql.user;//查看数据库中所用用户信息 create user username%;//创建用户 create user username% identifie…

医学交互作用分析步骤和目的(R语言)

医学交互作用分析的目的和用途&#xff08;R语言&#xff09; 医学交互作用分析一直是医学数据分析的组成部分&#xff0c;总结最近的一些认识。 目的&#xff1a; 在独立危险因素鉴定的研究中&#xff0c;&#xff08;独立危险因素的&#xff09;交互作用可以作为独立危险因…

Javaweb后端登录会话技术jwt令牌

jwt生成与校验 是base4补位的 最后面是签名&#xff0c;签名不是base64&#xff0c;是通过签名算法加密后来的 令牌长度不是固定的&#xff0c;长度取决于原始内容&#xff0c;载荷&#xff0c;大小 头有&#xff0c;类型&#xff0c;签名算法 base64可以对任意的二进制数据进…

Mybatis操作数据库(注解+xml两个方式)

文章目录 1.个人回顾2.关于mybatis注解的说明3.字段和属性不匹配的解决方案3.1第一个方案3.2第二个方案3.3第三个方案 4.xml路径配置5.xml里面的字段映射 1.个人回顾 刚刚翻看了一下自己的这个之前写的博客&#xff0c;上一次和这个javaee相关的博客还是去年写的&#xff0c;也…

SysVinit和Systemd的系统运行级别

Linux运行级别 SysVinit系统(init守护进程)Linux系统运行级别SysVinit系统(init守护进程)查看Linux运行级别SysVinit系统(init守护进程)修改运行级别&#xff1a; Systemd守护进程Linux系统运行级别systemd查看运行级别Systemd查看系统当前运行级别 systemd修改运行级别multi-u…

Mysql-经典实战案例(11):深度解析Sysbench压测(从入门到MySQL服务器性能验证)

引言 如何用Sysbench压测满足mysql生产运行的服务器&#xff1f; Sysbench返回的压测结果如何解读&#xff1f; 别急&#xff0c;本文会教大家如何使用并且如何解读压测的结果信息&#xff0c;如何对mysql服务器进行压测&#xff01; 一、Sysbench核心功能全景解析 1.1 工…

vscode终端不识别npm 无法解析npm

vscode 用以管理员打开识别npm vscode 用普通用户打开不识别npm 刚换了一台新电脑&#xff0c;寻思安装各种环境&#xff0c;一顿操作猛如虎&#xff0c;当最后一个打开vscode后&#xff0c;运行项目发现&#xff0c;新建终端>npm run dev 无法识别。 在cmd 中 打node -…

springboot body 转对象强验证属性多余属性抛错误

在Spring Boot中&#xff0c;当使用RequestBody注解来接收HTTP请求中的JSON数据并将其转换为Java对象时&#xff0c;Spring默认会忽略额外的属性。这意味着如果发送的JSON包含一些目标对象中没有定义的属性&#xff0c;Spring不会报错&#xff0c;这些额外的属性会被简单地忽略…

01. Linux嵌入式系统学习笔记(一)(linux基础指令)

一. linux基础操作指令 1. 新建文件和目录 (1) 新建文件 touch 命令&#xff1a;用于创建空文件。 touch filename.txt 如果文件已存在&#xff0c;touch 会更新文件的访问时间和修改时间。 (2) 新建目录 mkdir 命令&#xff1a;用于创建目录。 mkdir directoryname 使…

Java 列表复制与对象引用

Java 列表复制与对象引用 一、知识点 1. 对象引用的基本概念 在 Java 中&#xff0c;List<School> 这样的集合存储的并不是真正的对象&#xff0c;而是对象的“地址”&#xff08;引用&#xff09;。就好比你有一个文件柜&#xff0c;文件柜里放的不是文件本身&#x…

如何理解 Apache Iceberg 与湖仓一体(Lakehouse)?

一、什么是湖仓一体&#xff08;Lakehouse&#xff09;&#xff1f; 湖仓一体是一种融合了数据湖的灵活存储能力与数据仓库的高效分析功能的现代数据架构。它通过整合两者的优势&#xff0c;解决了传统架构的局限性&#xff0c;为企业数据处理提供了更全面的解决方案。 数据湖…

Android面试总结之Android RecyclerView:从基础机制到缓存优化

引言 在 Android 开发中&#xff0c;RecyclerView是高效展示列表数据的核心组件。其强大的性能源于独特的视图复用机制和四级缓存体系。本文将结合源码与示例&#xff0c;带你深入理解RecyclerView的工作原理与优化策略。 核心组件 RecyclerView&#xff1a;作为容器视图&am…

【鸿蒙开发】Hi3861学习笔记- TCP客户端

00. 目录 文章目录 00. 目录01. TCP概述02. TCP应用场景03. TCP和UDP比较04. TCP相关API05. TCP编程流程06. 硬件设计07. 软件设计08. 实验现象09. 附录 01. TCP概述 TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接、可靠的传输层协议&#xff0c;旨…

【负载均衡系列】Keepalive

一、Keepalived 的核心功能 Keepalived 是一款用于实现 ​高可用(HA)​ 和 ​负载均衡 的开源工具,核心基于 ​VRRP(Virtual Router Redundancy Protocol)​ 协议,工作在网络四层(传输层)和七层(应用层)。 主要用途: 通过虚拟IP(VIP)实现服务高可用(主备切换)。…

2025-03-25 学习记录--C/C++-PTA 习题9-3 平面向量加法

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 习题9-3 平面向量加法 本题要求编写程序&#xff0c;计算两个二维平面向量的和向量。 输入格式: ❀ 输入在…

23种设计模式-桥接(Bridge)设计模式

桥接设计模式 &#x1f6a9;什么是桥接设计模式&#xff1f;&#x1f6a9;桥接设计模式的特点&#x1f6a9;桥接设计模式的结构&#x1f6a9;桥接设计模式的优缺点&#x1f6a9;桥接设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是桥接设计模式…

python:music21 构建 LSTM+GAN 模型生成爵士风格音乐

keras_lstm_gan_midi.py 这是一个结合 LSTM 和 GAN 生成爵士风格音乐的完整Python脚本。这个实现包含音乐特征提取、对抗训练机制和MIDI生成功能&#xff1a; import numpy as np from music21 import converter, instrument, note, chord, stream from tensorflow.keras.mode…

go:前后端分离

1.前端代码 新建一个前端文件夹&#xff0c;在该文件夹下新建一个.html文件&#xff0c;写入自己的html代码。 前端搞定。 2.后端代码 其核心是挂载路由接受前端传来的数据核心代码如下&#xff1a; func main() { // 服务运行提示 fmt.Println("go web server is runn…

大数据学习(86)-Zookeeper去中心化调度

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…