自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

指向NULL

和你们一起进步的人

  • 博客(30)
  • 收藏
  • 关注

原创 IPC(一)—— 匿名管道 pipe

IPC 方法Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。常用的进程间通信的方式有:管道 (使用最简单)信号 (开销最小)共享映射区 (无血缘关系)本地套接字 (最稳定)管

2021-12-30 14:30:04 224

原创 回收子进程

一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。孤儿进程父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,称为init进程领养孤儿进程。僵尸进程进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。【注意】:僵尸进程是不能使用kill命令清除掉的。因为kill命令只是用来终止进程的,而僵尸进

2021-12-23 15:28:32 460

原创 exec函数族

exec 函数族fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。将当前进程的.text、.data替换为所要加载的程序的.text、.data,然后让进程从新的.text第一条指令开始执行,但进程ID不变,换核不换壳。有以下6种exec开头的函数:#i

2021-12-22 14:02:25 230

原创 创建子进程

fork创建一个子进程。SYNOPSIS#include <unistd.h>pid_t fork(void);RETURN VALUE一旦调用成功父进程中的 fork 会返回子进程 PID,而子进程的 fork 会返回0;调用失败父进程中 fork 返回-1,没有子进程创建出来。【注意】:不是 fork 函数能返回两个值,而是 fork 后,fork 函数变为两个,父子需各自返回一个。创建单个子进程模型【注意】:父进程创建子进程后,两者竞争 cpu,如要保证子进程先于父

2021-12-21 10:17:18 880

原创 linux 环境变量

环境变量,是指在操作系统中用来指定操作系统运行环境的一些参数。特征本质上是字符串;有统一的格式:名=值[:值];值用来描述进程环境信息;存储形式与命令行参数类似。char *[]数组,数组名environ,内部存储字符串,NULL作为哨兵结尾。使用形式与命令行参数类似。加载位置与命令行参数类似。位于用户区,高于stack的起始位置。每个进程可以设定自己的环境变量。引入环境变量表须声明环境变量。extern char ** environ;查看环境变量的值echo $环境变量,

2021-12-14 15:38:02 823

原创 目录操作相关函数

Linux 系统函数:chdirSYNOPSIS:修改当前进程路径;#include <unistd.h>int chdir(const char *path);DESCRIPTION:path:要改变的工作目录,作用类似 cd 命令;RETURN VALUE:成功返回0,失败返回-1;getcwdSYNOPSIS:获取当前进程工作目录;#include <unistd.h>char *getcwd(char *buf, size_t si

2021-12-14 08:45:39 271

原创 PCB进程控制块

PCB 重要成员每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体,定义在 /usr/src/linux-headers-4.15.0-142-generic/include/linux/sched.h 内核头文件中(使用 uname -r指令查询 linux 版本),其内部有很多成员,我们重点掌握以下几部分即可。进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示。进程的状态,有就绪、运行、挂起、停止等状态。

2021-12-13 14:26:03 1485

原创 初识cpu取指与MMU

CPU取指开始程序存在于硬盘中,加载程序到内存中产生进程,内存要比硬盘的存储空间小,但读写速度更快;而cache要比内存的存储空间要小价格昂贵,但读写速度比内存更快;寄存器存在于CPU内部,数量少价格昂贵,但读写速度更快;CPU从cache中读取数据要经过预取指令,译码,执行三个步骤,执行的结果写入寄存器反馈到cache,内存,最后进行外设的显示或将数据写回硬盘等操作。cpu读取指令所经历的存储就像上图的金字塔形,越往上存储的容量越小,价格越贵,读写速度越快。MMU虚拟地址:可用的地址空间有4G

2021-12-10 10:44:36 552

原创 文件操作相关函数

statSYNOPSIS:#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>/* 穿透函数,如果文件是软连接可以追踪到链接的文件 */int stat(const char *pathname, struct stat *buf);/* 文件打开后传入文件描述符 */int fstat(int fd, struct stat *buf);/* 不穿透,读出的就是软链接文件的大

2021-12-01 15:36:12 65

原创 系统IO函数(open read write lseek...)

openSYNOPSIS:#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);DESCRIPTION:pathname:打开文件的路径;flags:打开方式;必须包含以下中的一个

2021-11-10 10:31:21 123

原创 C库IO函数

FILE结构体C库函数除了 fopen 大多都会传入一个文件指针 FILE* ,FILE是一个结构体,其中包含以下重要的字段;文件描述符:用于索引到对应的磁盘文件;文件读写位置指针:读写文件过程中,指针的实际位置;注意:写入文件后,指针自动移动,所以未关闭文件的情况下直接读取时要注意移动指针的位置;I/O缓冲区:其实就是一个块内存地址,默认大小为8k,作用是减少对硬盘的读写次数,比如频繁写入时,是先存到缓冲区再一次性写入;注意缓冲区是C库函数提供的,不需要用户关心,linux系统函数张丽红也没有缓

2021-10-27 10:22:42 78

原创 makefile函数使用

在函数调用时必须指定函数名以及函数操作使用的参数。函数处理的结果将返回到makefile文件中的调用点,其方式和变量替换一样。1. 函数调用语法$(function arguments)#或者${function arguments}function 是函数名,是make内建函数列表中的一个,也可以使用创建函数 call 创建自定义的函数。arguments 是该函数的参数。参数和函数名之间用空格或tab键隔开,如果有多个参数,它们之间用逗号隔开。注意:如果在参数总包含变量引用或其

2021-09-29 10:20:28 178

原创 Makefile条件语句

条件语句可以将一个变量与其它变量的值相比较,或将一个变量与一字符串常量相比较,从而确定执行或忽略makefile文件中一部分脚本。1. 条件语句语法条件语句使用三个指令:ifeq、else 和 endif。ifeq 语句是条件的开始,并指明条件。它包含两个参数,它们被逗号分开,并被阔在圆括号内。运行时首先对两个参数变量替换,然后进行比较。跟在 ifeq 后面的是符合条件时执行的命令,否则它们将被忽略。如果前面的条件失败,else 指令将导致跟在其后面的命令执行。else 指令是可选的。endif

2021-09-26 14:01:16 1257

原创 Makefile变量

使用变量变量是在makefile中定义的名字,其用来代替一个文本字符串,这个文本字符串就是变量得值。这些值可以用来替代目标,依赖,命令以及makefile中其它部分。注意:变量名是大小写敏感的,而且变量分配时,变量值前面的空格被忽略。1. 变量的引用美元符号后跟用圆括号或大括号括住变量名则可引用变量的值,例如:$(foo)或${foo}。如果美元符号后面跟一个字符,例如:$x,则该字符将被处理为单字符的变量名,除了使用自动变量的情况,这种用法几乎不会使用。...

2021-09-24 10:50:04 578

原创 gdb调试命令

gdb是linux下的调试工具,要想使用gdb进行调试千万不要忘记在编译选项中加入-g,否则将无法调试。启动gdb:gdb app。基本命令:l:查看源码l:默认显示main函数所在文件前10行,可连续输入该命令继续向下查询。l file:line:查看file文件的第line行。l file:func:查看file文件中的func函数。b/break:设置断点,注意:如果设置for循环断点,要打在for循环体内。b/break line:在第line行打断点,也可以给其它文件设置

2021-08-30 13:32:16 278

原创 动态库详解

动态库1. 命名规则lib + 库的名子 + .so,例如:libtest.so。2. 制作过程其实动态库就是将一些生成的与位置无关的.o文件打包到一起得到一个.so文件,所以制作过程主要有三大步,我们举一个简单的例子来说明,比如我现在要实现一个算法库,该库只实现简单的加减乘除4个功能。准备原材料:首先需要编写好必要的源文件以及头文件,我们把头文件放到include目录,源文件放到src目录,即将生成的库文件放到lib目录中。生成与位置无关的代码(生成与位置无关的.o):使用参数-

2021-08-24 15:39:54 2729 2

原创 静态库详解

静态库1 命名规则lib+name+.a,例如:libtest.a。2 制作过程其实静态库就是由很多生成的.o文件打包到一起得到的一个.a文件,所以制作过程主要有三大步。我们举一个简单的例子来说明,比如我现在要实现一个算法库,该库只实现简单的加减乘除4个功能。准备原材料:首先需要编写好必要的源文件以及头文件,我们把头文件放到include目录,源文件放到src目录,即将生成的库文件放到lib目录中,由于例子比较简单这里不列出源代码的内容了,重点看一下过程。生成对应的.o文件:这里我

2021-08-18 17:30:08 1734

原创 ❤️gcc编译选项❤️

gcc是一个可以编译多种语言的编译器。1. gcc编译程序的主要过程一个c源文件要经过预处理、编译、汇编和链接等4个步骤才能变为可执行文件。下面是hello.c的源代码作为例子:#include <stdio.h>#define VAL1 10#define VAL2 20int main(int argc, char **argv){ printf("VAL1:%d, VAL2:%d, ADD:%d\n", VAL1, VAL2, VAL1+VAL2); return

2021-08-18 09:52:31 151

原创 ❤️C语言内部机制❤️

在学习C语言基础语法的时候,我们很容易理解函数的调用,比如我们写好一个加法运算的接口,在main函数中定义两个变量,赋好值,再调用写好的接口,就可以得到结果,好像是再简单不过了。其实这件事说简单也简单说复杂也复杂,下面我们以一个简单的arm裸板程序为例揭开C语言的内部机制。首先是一段用汇编编写的启动代码,主要干两件事:一个是设置栈,一个是调用main函数。start.S:.text.global _start_start: ldr sp, =4096 bl mainhalt: bl

2021-08-12 16:59:50 104

原创 『解决ping问题』windows ubuntu 开发板三者互连如何设置

嵌入式开发中,我们经常会遇到ping问题,也就是windows主机,虚拟机和开发板之间互相ping不通的问题,看了韦东山老师关于此部分的讲解做了以下总结。1. 确定虚拟机使用的网卡先来看几种应用场景:情景一:PC机使用有线网卡A直接连接开发板。这种情况下我们使用了有线网卡A最终连接了开发板,所以虚拟机要设置有线网卡A作为桥接网卡。情景二:PC机使用无线网卡A连接路由器,开发板连接到同一路由器的有线网卡。这种情况下我们使用了无线网卡A最终连接了开发板,所以虚拟机要设置无线网卡A作为桥接网卡

2021-08-06 16:38:34 597

原创 ❤️善用宏——定义及初始化变量结构体和数组❤️

开始使用STM32做项目的时候,发现当使用一些接口去创建task,或者使用定时器等等需要提前定义一些变量和宏,然后将他们作为参数传入到接口中。比如:/* 这些定义每个task都是需要的,只是变量的名字和一些宏的值不同而已 */#define TSK1_TASK_PRIO 3#define TSK1_STK_SIZE 128OS_TCB Tsk1TaskTcb;CPU_STK TSK1_TASK_STK[TSK1_STK_SIZE];void task1_main(void *p_arg);

2021-08-03 09:54:46 3653

原创 路径查找之进入文件系统安装点

1. 关于路径名查找1.1 处理过程VFS路径名查找,也就是如何从文件路径名导出相应的索引节点。这个处理过程可以简述为:检查与第一个名字匹配的目录项,获得相应的索引节点。然后,从磁盘读出包含那个索引节点的目录文件,并检查与第二个名字匹配的目录项,以获得相应的索引节点。对于包含在路径中的每个名字,这个过程反复执行。1.2 绝对路径与相对路径如果路径名的第一个字符是“/”,那么这个路径是绝对路径,因此从 current->fs->root(进程根目录)所标识的目录开始搜索。否则路径是相对路径

2021-07-30 13:02:44 245

原创 安装根文件系统

1. 如何安装安装根文件系统是系统初始化的关键部分。Linux内核允许根文件系统存放在很多不同的地方,比如硬盘分区、软盘、通过NFS共享的远程文件系统,设置保存在ramdisk中(RAM中的虚拟块设备)。接下来讨论的是假定根文件系统存放在硬盘分区。安装根文件系统分两个阶段:内核安装特殊rootfs文件系统,该文件系统仅提供一个作为初始安装点的空目录。内核在空目录上安装实际根文件系统。rootfs文件系统的存在,允许内核容易地改变实际根文件系统。事实上,在某些情况下,内核逐个地安装和卸载几个根文

2021-07-27 09:26:33 379

原创 VFS之普通文件系统安装

1. VFS层安装普通文件系统分析之所以称之为普通安装是因为接下来讨论的是将一个文件系统安装在一个已安装文件系统之上的情形。使用 mount() 系统调用来安装一个普通文件系统,将会调用它的服务例程 sys_mount() 函数。1.1 sys_mount()/** * @dev_name: 文件系统所在的设备文件的路径名 * @dir_name: 安装点路径名 * @type: 文件系统类型 * @flags: 安装标志 * @data: 指向一个与文件系统相关的数据结构的指针(可能

2021-07-24 22:23:23 309 2

原创 VFS各对象间的联系

1. VFS主要数据结构间的联系前面我在其他博客文章中已经整理了VFS主要数据结构的说明,这里主要是以一个例子将它们联系起来。假设/home目录下有一个用户名为book,在book目录下有两个文件,文件b是文件a的硬链接,同一时刻有三个进程在读取文件,其中有两个进程访问了同一文件a,另外一个进程访问了文件b,图示如下:文件描述符 task_struct 中的 files 字段中的 fd 指向该进程已打开文件的指针数组,其中前三个索引指向的文件对象默认被占用,所以用户打开的文件从索引3开始分配。每个进

2021-07-22 11:27:34 339 2

原创 VFS数据结构之(其它结构)

1. 与文件系统相关的数据结构1.1 文件系统类型1.1.1 file_system_type 数据结构用来描述特定文件系统的结构。struct file_system_type { const char *name; /* 文件系统名 */ int fs_flags; /* 文件系统类型标志 */ int (*get_sb) (struct file_system_type *, int, const char *, void *, struct

2021-07-20 16:31:32 170

原创 VFS数据结构之(file)

1. 文件对象(file object)文件对象描述进程怎样与一个打开的文件进行交互。文件对象是在文件被打开时创建的。注意:文件对象在磁盘上没有对应的映像,因此file结构体中没有dirty字段表示文件对象是否被修改。1.1 文件数据结构struct file { union { struct list_head fu_list; /* 用于通用文件对象链表的指针 */ struct rcu_head fu_rcuhead; /* 回收文件对象时,由RCU描述符使用 */ } f_u

2021-07-19 15:51:28 344 1

原创 VFS数据结构之(dentry)

1. 目录项对象(dentry object)VFS把每个目录看作一个文件,由若干子目录和文件组成。对于进程查找路径名中的每个分量,内核都为其创建一个目录项对象;目录项对象将每个分量与其对应的索引节点相联系。例如/tmp/test,内核会分别为“/”,“tmp”,“test”创建目录项。注意,目录项对象在磁盘上没有对应的映像,所以dentry中不包含判断dirty的标志。引入目录项结构是很有必要的,因为同一个文件有且仅有一个inode对象表示,而由于硬链接的存在,对同一文件的访问可以通过不同的文件名,所

2021-07-19 12:41:39 653 1

原创 VFS数据结构之(inode)

1. 索引节点对象(inode object)文件系统处理文件所需要的所有信息都放在索引节点数据结构中。文件名可以改,但索引节点对文件是唯一的。每个索引节点对象都会复制磁盘索引节点包含的一些数据,比如分配给文件的块数。1.1 索引节点数据结构struct inode { struct hlist_node i_hash; /* 用于散列链表的指针 */ struct list_head i_list; /* 用于描述索引节点当前状态的链表的指针 */ struct list_head i_s

2021-07-17 10:02:07 552

原创 VFS数据结构之(superblock )

通用文件模型VFS的思想是把不同种类文件系统的共同部分抽象出来,其中有一个字段用来指向所支持的实际文件系统的操作方法。这些抽象出来的数据结构就是VFS的通用文件模型。你可以把通用文件模型看作面向对象的,结构体中既定义了数据也定义了其上的操作方法。这个模型能够表示所有支持的文件系统,因此要实现具体的文件系统就必须要把其物理组织结构转换为虚拟文件系统的通用文件模型才可以使用VFS。例如:通用模型中每个目录被看作一个文件,包含若干文件和其他子目录。但是存在几个非Unix基于磁盘的文件系统,他们利用文件分配表

2021-07-15 14:15:51 502 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除