<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[mj5742356的专栏]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/mj5742356</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; mj5742356]]></copyright><item><title><![CDATA[掌握PCIe DMA 设计看这篇就够了]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/157464608</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/157464608</guid><author>mj5742356</author><pubDate>Wed, 28 Jan 2026 09:37:25 +0800</pubDate><description><![CDATA[本文详细介绍了PCIe DMA通信系统的开发实现，涵盖RP(Root Port)和EP(Endpoint)两端驱动设计。主要内容包括：1)系统架构与拓扑结构，展示RP与EP通过PCIe链路连接；2)驱动框架设计，分析RP端PCI驱动和EP端EPF驱动的核心数据结构；3)BAR空间设计用于数据共享；4)DMA引擎操作流程；5)MSI中断机制实现；6)数据传输方法对比Local DMA与Remote DMA；7)调试接口设计。文章提供了完整的驱动代码示例(demo-pcie-dma-test.c和pci-epf]]></description><category></category></item><item><title><![CDATA[Linux 自旋锁的实现]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/149098576</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/149098576</guid><author>mj5742356</author><pubDate>Thu, 03 Jul 2025 19:47:07 +0800</pubDate><description><![CDATA[现在我们再来看看 100 个进程获取同一个自旋锁的情况，开始 1 个进程获取了自旋锁 L，后面继续来了 99 个进程，它们都要获取自旋锁 L，但是它们必须等待，这时第 1 进程释放了自旋锁 L。很有可能最后来的进程最先获取自旋锁 L，这对其它等待的进程极其不公平，为了解决获取自旋锁的公平性，Linux 开发出了排队自旋锁。你可以这样理解，想要给进程排好队，就需要确定顺序，也就是进程申请获取锁的先后次序，Linux 的排队自旋锁通过保存这个信息，就能更公平地调度进程了。结合刚才的代码，我给你做个解读。]]></description><category></category></item><item><title><![CDATA[X86 CPU 工作模式]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/149090452</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/149090452</guid><author>mj5742356</author><pubDate>Thu, 03 Jul 2025 14:12:54 +0800</pubDate><description><![CDATA[第四步，开启长模式，要同时开启保护模式和分页模式，在实现长模式时定义了 MSR 寄存器，需要用专用的指令 rdmsr、wrmsr 进行读写，IA32_EFER 寄存器的地址为 0xC0000080，它的第 8 位决定了是否开启长模式，MSR是CPU的一组64位寄存器，可以分别通过RDMSR和WRMSR 两条指令进行读和写的操作，前提要在ECX中写入MSR的地址。长模式相比于保护模式，增加了一些通用寄存器，并扩展通用寄存器的位宽，所有的通用寄存器都是 64 位，还可以单独使用低 32 位。]]></description><category></category></item><item><title><![CDATA[Linux 调度算法简述]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/107139488</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/107139488</guid><author>mj5742356</author><pubDate>Sun, 05 Jul 2020 15:40:39 +0800</pubDate><description><![CDATA[今天在网上看到一些讲linux调度算法和策略的文章，好多都是错误，想当年我也被这种文章误导过很多次。

特意针对linux 调度简单梳理一下，确保大家能够分辨是非。

linux 的进程调度按照大的区分，有两类，1.RT的线程 2.普通线程， 一个线程是RT线程还是普通线程，内核都有接口设置的，

RT线程采取的策略是SCHED_FIFO 和SCHED_RR两种调度算法，这两种调度算法只有一个区别，就是SCHED_RR对同优先级的线程会时间轮转，而SHCED_FIFO则不会，直到优先级高的主动休眠或者放弃.]]></description><category></category></item><item><title><![CDATA[Linux 内存管理四]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/104147926</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/104147926</guid><author>mj5742356</author><pubDate>Sun, 02 Feb 2020 18:55:23 +0800</pubDate><description><![CDATA[Page cache 理解，Page cache 实际是一块内存，linux 读取一个文件，会先看看page cache 是否命中，如果没有命中，先把文件读到page cache ，再从page cache 读文件。如果是写的，也是先写入page cache区域，linux应用程序的write 已经返回，什么时候真正写入磁盘，这是linux内存磁盘替换算法的事情。
	
	Linux 读写文件有两种...]]></description><category></category></item><item><title><![CDATA[Linux 内存管理三]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/104136707</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/104136707</guid><author>mj5742356</author><pubDate>Sat, 01 Feb 2020 18:18:52 +0800</pubDate><description><![CDATA[本节主要涉及下面这些概念，搞清楚我们在linux下面写一个应用程序究竟耗费了多少内存，也是我们查内核泄漏的指标。

VSS- Virtual Set Size

RSS- Resident Set Size

PSS- Proportional Set Size

USS- Unique Set Size

在linux 里面大量的存在内存共享的概念，比如我们的libc 库，加入我们有100个程序...]]></description><category></category></item><item><title><![CDATA[linux 内存管理 二]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/104126429</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/104126429</guid><author>mj5742356</author><pubDate>Fri, 31 Jan 2020 18:09:25 +0800</pubDate><description><![CDATA[疫情憋在家，继续写下笔记，Buddy 算法把空闲页面管理起来，一个已经被占用的页面，其他人肯定不能申请到的，这些页面都是4k 8k 16k .... ,无论是在内核还是在应用，有时候都要申请很小的内存。比如说我们在内核中需要申请16Bytes，Buddy 还是申请4K的内存，这样就很乱费，所以在内核里面会进行内存的二次管理，在Buddy中申请的内存进行切割，内核中这种机制叫做slab。

Slab...]]></description><category></category></item><item><title><![CDATA[QNX-编译环境]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/52503717</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/52503717</guid><author>mj5742356</author><pubDate>Fri, 31 Jan 2020 10:44:33 +0800</pubDate><description><![CDATA[因为工作需要开始接触QNX实时操作系统，第一步先了编译环境，这样才能随意改过BSP，驱动和应用程序。

刚开始接触，基于QNX IDE 进行分析，QNX在images下面有一个住Make file 文件，其中描述了最终产出的目标

文件，也就是IPL 与 （startup+OS）.而整个QNX系统中有多个makefile，都是主Makefile递归循环调用的。

首先主makefile分析

RO...]]></description><category></category></item><item><title><![CDATA[Linux 内存管理一]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/104121565</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/104121565</guid><author>mj5742356</author><pubDate>Fri, 31 Jan 2020 10:12:36 +0800</pubDate><description><![CDATA[疫情在家，整理下以前的学习笔记， 作为linux 三个最重要的部分之一（进程，io，内存），内存管理是非常重要的，是深入理解linux各个部分的基础，linux的内存管理与其他rtos的内存管理不一样，他是一个“富” os，也就是支持很多的应用同时跑，还需要支持应用之间的内存隔离。Linux 内存不仅仅用于内存，比如作为硬盘的补充，硬盘本身也可以作为内存来使用。



硬件原理和分页管理
...]]></description><category></category></item><item><title><![CDATA[Linux 内核调试]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/104121477</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/104121477</guid><author>mj5742356</author><pubDate>Fri, 31 Jan 2020 10:05:32 +0800</pubDate><description><![CDATA[肺炎疫情憋在家里，总结一下很久之前的学习笔记，先说说系统开发工程都需要的内核调试方面。主要是结合以前的项目调试经验和笔记，欢迎大家补充，还记得以前从0 开始写一个bootloader，把一个linux 系统在三星s3c2410上跑起来，基本就是使用printk 来调试的。





上面这一段就是一个典型的IC 原厂的工程师在最开始把linux移植到芯片上的bootargs，是bootloade...]]></description><category></category></item><item><title><![CDATA[linux驱动开发-阻塞的字符设备]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/32330513</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/32330513</guid><author>mj5742356</author><pubDate>Fri, 02 Feb 2018 17:11:26 +0800</pubDate><description><![CDATA[阻塞和非阻塞是设备I/O访问的两种方式。

我们访问一个命名管道时如果管道中没有内容，则会阻塞，等待数据进入管道。那么我们如何来编写一个带阻塞功能的字符设备呢？
linux 的等待队列能很好的实现无数据阻塞。（#include ）
定义一个等待队列有两种方式。
1.先定义，在初始化。init_waitqueue_head()函数会将自旋锁初始化为未锁，等待队列初始化为空的双向循环链表。]]></description><category></category></item><item><title><![CDATA[lcd fb参数如何计算]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/79228164</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/79228164</guid><author>mj5742356</author><pubDate>Thu, 01 Feb 2018 14:31:18 +0800</pubDate><description><![CDATA[Linux内核的amba lcd控制器使用clcd_panel结构体表示一个LCD屏的硬件参数：/* include/linux/fb.h */

struct fb_videomode {

     const char *name;     /* optional */

     u32 refresh;          /* optional */

     u32 ]]></description><category></category></item><item><title><![CDATA[C++快速入门-默认参数]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/51510964</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/51510964</guid><author>mj5742356</author><pubDate>Thu, 26 May 2016 22:03:57 +0800</pubDate><description><![CDATA[默认参数是C语言中没有的概念，其实也是足够简单啦，但是有一点要注意，
如果一个函数有多个参数，其中某一个使用默认参数，那么这个默认参数之后的参数全部要使用默认参数。
比如示例中，b=2 ，那么c一定要设置默认参数，其实也很好理解，因为只有这样才能区分各个参数和赋值的对应关系。
真的很简单。


#include 

void func(int a , int b = 2, int c]]></description><category></category></item><item><title><![CDATA[C++快速入门-标准输入输出]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/51510929</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/51510929</guid><author>mj5742356</author><pubDate>Thu, 26 May 2016 21:56:31 +0800</pubDate><description><![CDATA[C语言有标准输入输出，C++同样有。标准输入输出是标准库提供的一套API。
cin >> num ;就是输入一个整数，而cout 
是不是非常简单


简单示例代码：
#include 

using namespace std;
int main(void)
{
	int num;

	cin >> num;	

	cout << "sdfsdf" << "num = " << nu]]></description><category></category></item><item><title><![CDATA[C++快速入门-命名空间]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/51510820</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/51510820</guid><author>mj5742356</author><pubDate>Thu, 26 May 2016 21:51:19 +0800</pubDate><description><![CDATA[命名空间是c++中的一个非常基本的概念，其实在其他很多语言中也有类似的概念，有点类似比较高级版本的C语言中的头文件作用域。
最常见的命名空间引用语句时 using namespace std； 这句的意思是在本语句之后可以引用std命名空间中的接口，std值标准库中的命名空间。
命名空间的主要作用是解决同名冲突。设计者可以根据需要指定有名字的空间域，把一些全局对象放在不同的命名空间中，从而与其]]></description><category></category></item><item><title><![CDATA[C++快速入门-简单概要]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/51379926</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/51379926</guid><author>mj5742356</author><pubDate>Thu, 12 May 2016 03:14:02 +0800</pubDate><description><![CDATA[经常听到一些熟悉C语言的朋友谈到如何快速入门C++，很多人觉得C++很难，感觉入门需要花很大的精力，其实并非这样，C++是一门面向对象的语言，
只要把思维方式从C的面向过程转变到C++的面向对象编程，就能够很快速的学习C++，面向对象更加符合日常的世界的构造方式，当我们有想不明白C++某些概念和
实现的时候，联想一些我们周围生活的世界，也许就能理解了。
废话少说，先罗列C++的最重要的两个基]]></description><category></category></item><item><title><![CDATA[linux设备驱动-ioremap]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/33732873</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/33732873</guid><author>mj5742356</author><pubDate>Mon, 23 Jun 2014 15:14:49 +0800</pubDate><description><![CDATA[void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
void *ioremap(unsigned long phys_addr, unsigned long size)
入口： phys_addr：要映射的起始的IO地址；
size：要映射的空间的大小；
flags：要映射的I]]></description><category></category></item><item><title><![CDATA[linux设备驱动开发-异步通知机制]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/33731199</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/33731199</guid><author>mj5742356</author><pubDate>Mon, 23 Jun 2014 14:54:34 +0800</pubDate><description><![CDATA[设备驱动中异步通知编程还是比较简单的，主要就是一些数据结构，和两个函数：
数据结构：fasync_struct结构体
函数：1）处理FASYNC标志变更的函数int fasync_helper(int fd, struct file *filp, int mode ,struct fasync_struct **fa);
        2) 释放信号用的函数void kill_fasync]]></description><category></category></item><item><title><![CDATA[linux设备驱动开发-高级字符设备操作poll]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/33730117</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/33730117</guid><author>mj5742356</author><pubDate>Mon, 23 Jun 2014 14:02:06 +0800</pubDate><description><![CDATA[在用户程序中，select()和poll()也是与设备阻塞与非阻塞访问息息相关的，使用非阻塞I/O的应用程序通常会使用select和poll系统调用查询是否可对设备进行无阻塞的访问。select系统调用最终会引发设备驱动中的poll函数被执行。
一、select()系统调用：
用于多路监控，当没有一个文件满足要求时，select将阻塞调用进程。
1.select()原型：



本文]]></description><category></category></item><item><title><![CDATA[linux设备驱动开发-设备阻塞访问的简单实现]]></title><link>https://blog.youkuaiyun.com/mj5742356/article/details/33717393</link><guid>https://blog.youkuaiyun.com/mj5742356/article/details/33717393</guid><author>mj5742356</author><pubDate>Mon, 23 Jun 2014 10:46:35 +0800</pubDate><description><![CDATA[当我们读取一个空的命名管道文件是，会阻塞等待，知道有新数据写入管道中。]]></description><category></category></item></channel></rss>