- 博客(45)
- 收藏
- 关注
原创 Makefile 语法和环境变量
...] ,此外还有波浪号 ~ ,它在文件名中有两种用途,一是表示当前用户 $HOME 目录,如 ~/test ,二是表示某用户的宿主目录,如 ~someone/test ,就是 someone 用户的宿主目录下的 test ,但在 Windows 或 MS-DOS 下用户没有宿主目录,那么此时 ~ 所指的目录就是环境变量 HOME。用作循环,把 list 字符串中的项逐一取出放入到 var 所指定的变量中,然后将 text 字符串返回,返回的字符串之间以空格隔开,循环结束时整体作为返回值返回。
2023-08-21 17:15:09
925
原创 移植 U-boot常见命令和重要环境变量
root=/dev/nfs nfsroot=[<服务端 IP>:]<根文件系统绝对路径>[,<NFS 其他可选选项,一般不设置>] ip=<客户端 IP>:<服务端 IP>:<网关地址>:<子网掩码>:<客户机名字,一般不设置为空>:<网卡名>:<自动配置,一般不用填 off >:<DNS0服务器IP地址,不用>:<DNS1服务器IP地址,不用>示例中 root=/dev/mmcblk2p3 ,即指明根文件系统存放在 mmcblk2 设备的分区 3 中,这取决于开发板的 mmc 设备和各设备的分区情况。
2023-08-14 18:51:01
902
原创 字符设备驱动 框架(未完)
系统调用是用户进入内核的接口层,它本身并非内核函数,在进入内核后,不同的系统调用会找到各自对应的内核函数,这些内核函数为系统调用的“服务例程”,而系统调用则是内核函数的“封装例程”,标准C库为每个系统调用设置了一个封装例程,系统调用已属于Linux内核,所以由此向下不再存在兼容与否的问题。文件系统中的字符设备:在Linux系统中一切皆文件,字符设备驱动加载成功后会在 /dev 下生成设备节点文件,通过操作这些特殊文件,可以实现操作硬件设备的目的。这意味着字符设备的读写操作是实时的,不会有额外的延迟。
2023-08-01 11:52:39
101
原创 驱动 CAN总线(未完)
CANL唤醒电平为 3.2V(休眠为 12V)(空闲为 5V)CANH休眠电平为 0V(空闲为 2.5V)CANL休眠电平为 0V(空闲为 2.5V)CANH唤醒电平为 1.8V(休眠为 0V)(空闲为 0V)CANH为 0V(空闲为 2.5V)CANL为 0V(空闲为 2.5V)唤醒电平为 12V(休眠为 0V)(空闲为 0V)CANH为 3.6V(空闲为 2.5V)+1.1。CANL为 1.4V(空闲为 2.5V)-1.1。CANL休眠电平为 2.5V。CANL休眠电平为 12V(空闲为 5V)
2023-07-27 16:17:23
280
原创 驱动 串口总线 UART(未完)
以字符为传输单位,一位一位的顺序传输,传输速率用波特率表示,单位为bps(1s发送多少bit),允许的波特率差异最大值为10%,超过此值,位的时序就会脱节,传输过程中两个字符间的时间间隔不固定,但同一个字符内位与位之间的时间间隔是固定的,协议规定传输方向为从低位传输(LSB)UART 驱动由于历史原因,实现过程并不像 IIC 或 SPI 那样,拥有独立的模块,而是基于 tty 字符设备框架实现的,注册 UART 驱动的过程实质上是注册 tty 设备驱动的过程,实现过程比较复杂。有校验位进行错误检测。
2023-07-06 16:35:51
844
原创 C语言 进程通讯 socket套接字(TCP/UDP)示例
domain:协议族,AF_xxx是地址族(address family),指明用什么协议的IP地址格式,PF_xxx是协议族(protocol family),指明用什么协议族,但是两种宏的值是一样的(如AF_UNIX == PF_UNIX),这是因为每种协议族都各只有一种IP地址格式,因此它们其实是一一对应的关系。TCP/IP协议族之所以能实现网络通讯,依靠的是网络层的IP协议,只是IP协议仅能做最基本的通讯,缺乏很多精细的功能,这需要传输层的TCP或UDP来提供。
2023-06-27 18:13:45
1775
原创 Linux 更改只读文件方法
2.vi 打开后输入命令保存(w空格!sudo空格tee空格%)之后出现提示,按 L 重新载入即可。1.用 gedit 方式打开。
2023-05-31 14:04:30
1644
原创 C语言 存储类型 和 类型限定符
在修饰变量时,只能在初次定义时初始化一次(储存在.data),若没有初始化则程序运行前内核将之初始化为0(储存在.bss),储存在静态区,整个程序运行期间不释放。被修饰的数组可赋值给其他数组,被修饰的数组不可将地址赋值给其他未被const修饰的指针(自然不可以)。在修饰函数时,表示被修饰的函数是在其他地方已经定义过的(函数默认是全局的),这样做省去因添加头文件而增加的其他不必要的函数,加速预处理阶段。被修饰的指针(在 * 前)不可赋值(指针的值)给其他未被const修饰的指针(自然不可以)。
2023-05-29 18:35:22
107
原创 C语言 sqlite3数据库
SELECT * FROM student WHERE score=98 OR name="李四";INSERT INTO student(id,name) values(1002, '李四');pazResult:查询结果 (char *的一维数组),[0, pnColumn-1]存储字段名称,后面存字段内容。INSERT INTO 表名 VALUES(, ,) //这种方式不能空,都要赋值。INSERT INTO 表名(, ,) VALUES(, ,) //这种方式可以空。
2023-05-27 15:27:30
366
原创 C语言 字符串相关函数
期间没有生成新的字符串,只是在str字符串内将首次出现的分割符替换成' \0 ',因此源str字符串会被更改,若起始位置即为分割符会被忽略(也不会跟随第一部分打印出来,会消失),返回str字符串获得第一个部分,若还想继续获得其余部分,只需再次调用strtok函数并将第一个参数置NULL,表示从上一次隐式保存的位置(this指针指向分割符的下一位)继续分解字符串,当this指针指向' \0 '时,表示分割完毕,此时返回NULL。返回值:字符串的长度,即字符数组中 '\0' 前有几个字符,不包括 '\0‘
2023-05-26 16:29:04
60
原创 结构体inode、file、FILE、stat、dirent和DIR、task_struct
一个文件的属性,供int stat((const char *)pathname, struct stat *statbuf)函数使用,从内核struct inode结构体获取到文件信息后存入struct stat结构体。,表示一个被打开的文件,每open一次就会生成一个struct file结构体,所以一个struct inode结构体可以对应多个struct file结构体,当文件被关闭时,内核释放该结构体。,表示一个静态文件,每个文件都会对应唯一的struct inode结构体。
2023-05-25 14:54:08
334
原创 块设备驱动
内核通过设备文件(文件描述符)来操作块设备,在打开块设备文件时,其文件操作file_operations结构体为def_blk_fops实例,然后调用驱动程序中定义的block_device_operations实例响应的函数,完成对块设备的控制。在块设备驱动中,将应用对块设备的操作分解成一个个I/O请求(struct bio),I/O调度算法可将连续的I/O请求合并成一个请求(struct request),然后用一个请求队列(struct request_queue)来管理这些请求。
2023-05-21 16:20:11
322
原创 内核空间分配内存 kmalloc和vmalloc 及 页式分配
kmallck分配低端内存(3G+896M以内),最大128k,必须是2的n次方,因为底层是基于__get_free_pages实现的,虚拟地址空间连续,物理地址空间也连续,即虚拟地址 = 3G + 物理地址。vmalloc从高端内存(低端内存+120M以内)处开始分配,得到的有可能是高端内存也有可能是低端内存,虚拟地址空间连续,物理地址空间不一定连续,分配的页必须一个一个的映射,效率不高,只在为获得大块内存时使用。返回值:分配的页的地址的编号,如0xffff880124470000,失败=0。
2023-05-19 10:52:31
141
原创 驱动 SPI总线
SPI 是 同步、串行、全双工、高速 通讯总线,采用主从模式(Master Slave)架构,一个 SPI 通讯系统必须且只能有一个主设备,提供时钟的为主设备(Master),接收时钟的为从设备(Slave),SPI 接口的读写操作,都是由主设备发起,SPI 只有主模式和从模式之分,没有读和写的说法,外设的读写操作是同步完成的,SPI 主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。中的SPI控制器,其中有芯片厂商编写的真正实现控制SPI硬件设备的驱动。
2023-05-18 16:53:30
389
原创 驱动 I2C总线
IIC 是 同步、串行、半双工 通讯总线,支持多主机多从机,同一时刻只能有一个主机和一个从机通讯,挂载的每个设备都有自己的地址(7 位或 10 位),从设备中的寄存器地址为 8 bit,设备数量受最大电容 400pF 限制,只有 2 条线scl 时钟线:低电平时,发送器向数据线上写,高电平时,接收器从数据线上读一个时钟周期收发 1 bit 数据,即写后立即读一帧共 9 个时钟周期(9 bit),前 8 bit 数据(先传最高位(MSB))(发送
2023-05-18 11:40:33
225
原创 驱动 外部按键中断的实现 并 使用Linux内核定时器实现按键消抖 示例
【代码】驱动 外部按键中断的实现 并 使用Linux内核定时器实现按键消抖 示例。
2023-05-16 16:12:19
294
原创 驱动 导出符号表
demoB:调用add函数,在编译demoB前需要将demoA模块下的Module.symbers拷贝(5.4内核)到demoB目录下,在编译demoB模块。当demoA模块编译完之后会生成一个Module.symvers符号表文件。demoA:提供add函数。
2023-05-15 18:06:09
60
原创 驱动 内核模块传参
3.对变量信息的详细描述(可以通过modinfo xxx.ko查看)perm:设置文件权限(0664)perm:设置文件权限(0664)_parm:要传参的变量名。desc:描述变量的字符串。1.接收命令行传递的参数。name:要传参的变量名。2.接收命令行传递的数组。name:要传参的变量名。nump:传递的成员个数。
2023-05-15 18:01:50
89
原创 驱动 内核定时器使用 示例
定时器频率配置在 .config中,内核固定不能修改。举例CONFIG_Hz = 250,即 1秒/250 = 4ms jiffies+1。全局变量 jiffies 用来记录自系统启动以来产生的节拍总数,启动时为0,此后每秒增加Hz(一秒内时钟中断次数)
2023-05-15 17:35:30
210
原创 驱动 控制GPIO子系统 框架
Linux Kernel 中,对于 GPIO 功能用 Gpiolib 来管理,作为中间层的 Gpiolib ,对上(其他 Drivers)提供一套统一的 操作 GPIO 的软件API,屏蔽了不同芯片的具体实现,对下(硬件)针对不同的芯片提供对应的一套 framework 用以物理实现功能(怎样增加 framework :需先实现 Specific Chip Driver ,再用 Gpiolib 提供的注册函数将其挂接到 Gpiolib 上即可)GPIOA_PULL 表示 GPIO A 的上下拉的配置。
2023-05-15 12:17:43
453
原创 驱动 获得设备树中信息
返回值:成功=struct property结构体指针,失败=NULL。index:索引号,当属性=多个<>时,0=第一个,1=第二个。index:索引号,当属性=多个值时,0=第一个,1=第二个。from:开始查找节点的起始位置,NULL=从根节点开始。type:节点的type属性对应的值,NULL=忽略。返回值:成功=节点结构体首地址,失败=NULL。返回值:成功=节点结构体首地址,失败=NULL。返回值:成功=节点结构体首地址,失败=NULL。返回值:成功=节点结构体首地址,失败=NULL。
2023-05-14 12:08:28
147
原创 字符设备驱动 I/O模型(实现阻塞) 等待队列 示例
另外还需多定义一个整型变量,int condition = 0,用于表示数据是否准备好。condition:定义的整型变量,表示数据是否准备好,也决定了是否休眠。初始化等待队列头,init_waitqueue_head(&wq)先 condition 置1,如果不置1即使唤醒也会再次进入休眠。定义等待队列头,wait_queue_head_t wq。timeout:超时返回,以 jiffy 为单位。queue:定义的等待队列头。wq:定义的等待队列头。
2023-05-11 14:16:31
142
原创 内核中并发和竞态 原子操作 示例
多条代码通过内联汇编成一个原子变量,视为一个不可被分割的整体(使用汇编语言实现,因为C语言不能实现)。原子操作需要硬件的支持,和架构有关,以ARMv6为分界点,实现方式有所不同,在ARMv6(不支持SMP)以下的版本中,1 关中断 2 操作变量 3 恢复中断;在ARMv6及以上版本中,使用strex和sdrex多次尝试,原子操作主要用于实现资源计数,很多引用计数(refcnt)就是通过原子操作实现的。返回值:成功 = 1,失败 =!
2023-05-10 18:01:57
73
原创 内核中并发和竞态 互斥体 示例
互斥体是比信号量更为专业的互斥机制,在进程未获取到互斥体后,会判断当前持有进程是否正在另一个 CPU 的临界区上运行,若是,它会假设该进程会很快执行完毕,从而进入自旋状态,否则会进入休眠状态(称为 spin 特性),此特性减少了进程切换的开销,例如当临界区较小时,互斥体比信号量效率高;尝试获取互斥体,不休眠直接返回,成功 = 1,失败 = 0,需要判断返回值再执行解锁操作。返回值:1 = 已被获取,0 = 未被获取。lock:定义的互斥体。lock:定义的互斥体。lock:定义的互斥体。
2023-05-10 17:33:27
86
原创 内核中并发和竞态 信号量 示例
信号量的本质就是一个描述临界资源有效个数的计数器,先申请信号量(未获得的休眠),然后访问临界资源,最后释放信号量。在jiffies个时钟节拍内休眠等待信号量,成功= 0,超时 = -ETIME。jiffies:在jiffies个时钟节拍内获取信号量,一个时钟节拍为4ms。val:信号量的初值,1 = 互斥,0 = 同步。申请信号量,不论成功与否都立即返回,失败 = 1。休眠可被信号打断,信号打断 = -EINTR。返回值:成功 = 0,失败 =!sem:定义的信号量。sem:定义的信号量。
2023-05-10 17:13:05
92
原创 内核中并发和竞态 自旋锁 示例
(原因:当一个 CPU 获取到一把自旋锁之后,开始执行临界区代码,此时假设他的时间片运转完毕,进程调度会主动触发调度将其调走,执行另一个线程/进程,结果恰巧了这个线程/进程也需要用到该自旋锁,而上一个线程/进程还在停留在临界区内未释放锁,导致本进程无法获取到锁而形成死锁,所以自旋锁为了规避此类情形的出现从而直接禁止对已经开始运行的临界区设置抢占标志)另一方面在中断上下文是不允许睡眠的,除了自旋锁以外的其他任何形式的锁都有可能导致睡眠或者进程切换,这是违背了中断的设计初衷,会发生不可预知的错误。
2023-05-10 10:22:27
102
原创 Linux .tar.xz文件压缩和解压
先 xz -d xxx.tar.xz(或者tar -xvJf),得到.tar文件。先 tar cvf xxx.tar xxx ,得到.tar文件。再 xz -z xxx.tar,得到.tar.xz文件。再 tar xvf xxx.tar,解压完成。
2023-05-09 09:24:20
530
原创 C语言 进程通讯 无名管道 有名管道 信号 (原始通讯)示例
可用于任意进程间的通讯,容量大小64K,管道文件大小为0,只起到标识作用,写入管道的数据存在内存上,不能使用lseek,半双工(同一时间内只能一端发另一端收),头文件<sys/types.h> <sys/stat.h>只能用于具备亲缘关系的进程间通信,容量大小64K,管道文件大小为0,只起到标识作用,写入管道的数据存在内存上,不能使用lseek,半双工(同一时间内只能一端发另一端收),头文件<unistd.h>返回值:成功 = 0,失败 = -1并置位errno错误码。
2023-05-08 10:34:25
160
转载 Linux中struct file结构体
例如用户调用系统调用read来读取该文件的内容时,那么系统调用read最终会陷入内核调用sys_read函数,而 sys_read最终会调用于该文件关联的struct file结构中的f_op->read函数对文件内容进行读取。文件预读状态,文件预读算法使用的主要数据结构,当打开一个文件时,f_ra中出了perv_page(默认为-1)和ra_apges(对该文件允许的最大预读量)这两个字段外,其他的所有西端都置为0。此处f_count的作用是记录对文件对象的引用计数,也即当前有多少个进程在使用该文件。
2023-05-06 17:04:45
191
原创 C语言 进程通讯 信号量集 示例
semflg:共有9个权限标志,可填 IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666 (判断IPC对象是否存在)获得key值,生成一个具有唯一性的ID,即队列的房间密码。返回值:成功 = 信号灯集的ID,失败 = -1。cmd:指令,SETVAL = 设置信号灯的值。返回值:返回值:成功 = 0,失败 = -1。返回值:成功 = key值,失败 = -1。nsops:要操作的信号量集成员的个数。返回值:成功 = 0,失败 = -1。初始化信号量集的成员的值。
2023-05-04 19:36:49
209
原创 C语言 进程通讯 共享内存 示例(附带内核地址映射ioremap+控制函数ioctl)
获得key值,生成一个具有唯一性的ID,即队列的房间密码。在亲缘关系进程通信的时候,可以直接key = IPC_PRIVATEpathname:程序范围内已经存在的文件名加绝对路径proj_id:只有8bits有效,若大于255则只有后8bits有效返回值:成功 = key值,失败 = -1创建共享内存key:IPC_PRIVATE 或 ftok()得到的值size:申请的共享内存大小(4K的倍数)
2023-05-03 14:13:45
675
原创 C语言 进程通讯 消息队列 示例
msgflg:共有9个权限标志,可填 IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666 (判断IPC对象是否存在)创建消息队列,若对应key值的IPC对象不存在,则创建,若存在,返回IPC对象的ID。msgtyp:要从消息队列中接收的消息类型,0 = 从消息队列中提取第一个信息。msgflg:接收方式,0 = 阻塞,IPC_NOWAIT = 非阻塞。返回值:成功 = 接收到的消息的正文大小,失败 = -1。返回值:成功 = 消息队列的ID,失败 = -1。
2023-05-03 13:41:02
449
原创 C语言 线程同步 条件变量 示例
返回值:成功 = 0,失败 =!若当前没有线程等待通知,cond指向非法地址,返回EINVAL。PTHREAD_COND_INITIALIZER:一个条件变量结构体常量。attr:条件变量作用于进程间还是线程间,NULL = 线程间。销毁条件变量,仍在使用时失败返回EBUSY。返回值:成功 = 0,失败 =!返回值:成功 = 0,失败 =!返回值:成功 = 0,失败 =!cond:定义的条件变量。cond:定义的条件变量。cond:定义的条件变量。cond:定义的条件变量。等待条件变量的唤醒信号。
2023-05-01 15:21:49
169
原创 C语言 线程同步 无名信号量 示例
psharad:0 = 在线程间共享,0!返回值:成功 = 0,失败 = -1并置位errno错误码。返回值:成功 = 0,失败 = -1并置位errno错误码。返回值:成功 = 0,失败 = -1并置位errno错误码。返回值:成功 = 0,失败 = -1并置位errno错误码。非阻塞,若获取不到(即值=0)立即返回。返回值:成功 = 0,失败 = -1。阻塞,若获取不到(即值=0)等待。sem:定义的无名信号量。sem:定义的无名信号量。sem:定义的无名信号量。sem:定义的无名信号量。
2023-05-01 15:21:06
149
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人