自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(37)
  • 收藏
  • 关注

原创 第12章--并发编程

到目前为止,我们主要将并发看做是一种操作系统内核用来运行多个应用程序的机制。但是,并发不仅仅局限于内核。它也可以在应用程序中扮演重要角色。例如,我们已经看到 Linux信号处理程序如何允许应用响应异步事件,例如用户键入 Ctrl+C,或者程序访问虚拟内存的一个未定义的区域。应用级并发在其他情况下也是很有用的:访问慢速 I/ 设备。与人交互。通过推迟工作以降低延迟。服务多个网络客户端。在多核机器上进行并行计算。使用应用级并发的应用程序称为并发程序。现代操作系统提供了三种基本的构造并发程序的方法

2023-11-14 17:02:19 73

原创 第14章--预处理器

我们将使用条件编译来实现这个魔术,你的函数应该叫做cpu_type,它不接受任何参数,当你的函数被编译时,在下面表中“已定义”列中的符号之一可能会被定义,你的函数应该从“返回值”列中返回对应的符号,如果左边列中的所有符号均未定义,那么函数就返回CPU_UNKNOWN这个值,如果超过一个符号被定义,那么其结果就是未定义的。为了扩展潜在市场,这个程序以几个不同的版本进行销售,每个版本有不同选项的组合–选项越多,价格就越高,你的任务是为一个打印函数实现代码,这样它可以很容易进行编译,产生程序的不同版本。

2023-11-04 14:00:00 69

原创 第13章--高级指针话题

4、编写一个名叫sort的函数,它用于对一个任何类型的数组进行排序,为了使函数更为通用,他的其中一个参数必须是一个指向比较回调函数的指针,该回调函数由调用程序提供,比较函数接受两个参数,也就是两个指向需要进行比较的值的指针,如果两个值相等,返回0,如果第一个值小于第二个返回小于零的整数,否则,返回大于零的整数。当所有以一个横杆开头的参数被处理完毕后,你应该返回一个指向下一个命令行参数的指针的指针(也就是一个诸如&argv[4]或argv+4的值)。1.一个指向需要排序的数组的第一个值的指针。

2023-10-28 14:30:00 73

原创 第12章--使用结构和指针

你可以假设节点数据结构在头文件singly_linked_list_node.h中定义,函数的第一个参数是一个指向链表根指针的指针,第二个参数是一个指向欲移除的节点的指针,如果链表并不包含该指针,函数就返回假,否则它就移除这个节点并返回真,把一个欲移除的节点的指针而不是欲移除的值作为参数传递给函数有哪些优点?1、编写一个函数,用于计数一个单链表的节点个数,它的唯一参数是一个指向链表第一个节点的指针,编写这个函数时,你必须知道哪些信息?4、编写一个函数,反序排列一个单链表中所有的节点。

2023-10-22 13:00:00 58

原创 第11章--动态内存分配

2、编写一个函数,从标准输入读取一列整数,把这些值存储于一个动态分配的数组中并返回这个数组,函数通过观察EOF判断输入是否结束,数组的第一个数是数组包含的值的个数,它的后面就是这些整数值。3、编写一个函数,从标准输入读取一个字符串,把字符串复制到动态内存分配的内存中,并返回该字符串的拷贝,这个函数不应该对读入字符串的长度作任何限制。1、请你尝试编写calloc函数,函数内部使用malloc函数来获取内存。4、编写一个程序,创建一个链表,包含一个链表头和三个动态分配的对象。

2023-10-14 13:00:00 46

原创 第10章--结构和联合

你的声明同时必须有一个名叫addr的unsigned short类型字段,可以访问所有的16位值,在你的声明中使用typedef来创建一个新类型,称为machine_inst。它还包括三个号码,你使用的那个号码,你呼叫的那个号码,以及你付账的那个号码,这些号码的每一个都由三个部分组成:区号,交换台和站号码,请为这些记帐信息编写一个结构声明。在许多机器中,由于不同的指令具有不同的格式,解码过程被复杂化了,在某个特定的机器上,每个指令的长度都是16位,并实现了下列各种不同的指令格式。位是从右向左进行标记的。

2023-10-09 11:10:17 31

原创 第9章--字符串、字符和字节

函数必须把密钥中的所有字符要么转换成大写,要么转换成小写(随你选择),并从单词中去除重复的字母,然后再用字母表中剩余的字母按照你原先所选择的大小写形式填充到key数组中去,如果处理成功,函数将返回一个真值,如果key参数为空或包含任何非字母字符,函数将返回一个假值。这个函数类似于strchr,但它的第三个参数指定ch字符在str字符串中第几次出现,例如,第三个参数为1,这个函数的功能就和strchr一样,如果参数为2,这个函数就返回一个指向ch字符在str字符串中第二次出现的位置的指针。

2023-10-01 13:00:00 66

原创 第8章--数组

提示:如果你采用一种叫做回溯法的技巧,就很容易编写出这个程序,编写一个函数,把皇后放在某行的第一列,然后检查它是否与棋盘上的其他皇后互相攻击,如果存在互相攻击,函数把皇后移到该行的第二列再进行检查,如果每列都存在互相攻击的情况,函数就应该返回,但是如果皇后可以放在这个位置,函数接着应该递归的调用自身,把一个皇后放在下一行,当递归调用返回时,函数再把原先那个皇后移到下一列。m1是一个x行y列的矩阵,m2是一个y行z列的矩阵,这两个矩阵应该相乘,结果存储于r中,它是一个x行z列的矩阵。

2023-09-23 14:00:00 24

原创 第7章--函数

5、实现一个简化的printf函数,它能够处理%d,%f,%s和%c格式码,根据ANSI标准的原则,其他格式码的行为是未定义的,你可以假定已经存在函数print_integer和print_float,用于打印这些类型的值,对于另外两种类型的值,使用putchar来打印。它把amount表示的值转化为单词形式,并存储于buffer中,这个函数可以在一个打印支票的程序中使用。提示:这个技巧很简单,你每发现一个数字,把当前值乘以10,并把这个值和新数字所代表的值相加。的值是40,请编写一个递归函数,计算。

2023-09-17 14:00:00 81

原创 第6章--指针

接着,再回到列表的头部重新开始,此时列表中尚未被剔除的第一个数是3,所以在3之后把每逢第3个数的倍数剔除,完成这一步骤之后,再回到列表开头,3后面的下一个数是4,但它是2的倍数,已经被剔除,所以将其跳过,轮到5,将所有5的倍数全部剔除,这样以此类推,反复执行,最后列表中未被剔除的数均为质数。函数的第二个参数不能被修改。注意除了2以外,所有的偶数都不是质数,稍微多想一下,你可以使程序的空间效率大为提高,方法是数组中的所有元素只对应奇数,这样,你在相同的数组空间内,你可以寻找到的质数的个数大约是原先的两倍。

2023-09-10 13:00:00 27

原创 第5章--操作符和表达式

2、编写一个程序,从标准输入读取字符,并把它们写到标准输出中,所有非字母字符都完全按照它的输入形式输出,字母字符在输出之前进行加密。加密的方法很简单:每个字母被修改为在字母表上距其13个位置(前或后)的字母,例如,A被修改为N,B被修改为O,Z被修改为M,以此类推,注意大小写字母都应该被转换。第一个函数把指定的位设置为1,第二个函数把指定的位清零,如果value的值为1,第三个函数就把指定的位清零,否则置1,至于最后一个函数,如果参数中指定的位不为零就返回真,否则返回假。假定整数中的位是从右向左进行编号。

2023-09-02 15:00:00 27

原创 第4章--语句

这个函数将数组src中的字符串复制到数组dst,但是有这些要求:刚好n个字符被存储到dst数组,如果src字符串的长度比n小,那么你需要添加足够的NULL字符使得有n个字符被存储,如果src中字符串的长度大于或等于n,那么复制n个字符后停止,这种情况下不是以NULL结尾,注意调用copy_n时应该在dst[0]到dst[n-1]存储,与src的长度无关。当函数发现一个或多个地方有一个或连续多个的空格组成,就把它们改成单个字符,注意当你遍历整个字符串时要确保它以NUL字符结尾。

2023-08-25 13:00:00 28

原创 第2章--基本概率

1、写一个程序,包含三个函数分别位于不同的文件中,第一个函数increment接受一个整型参数并且返回这个参数加一后的值,这个函数位于文件increment.c中,第二个函数叫做negate,同样接受一个整型参数并且返回它的相反数,最后一个函数是main函数,需要调用其他两个函数并且用10,0,-10的值测试并打印出来。2、写一个程序从标准输入中读取c源程序并且确定花括号是否正确的配对,提示:你不用担心括号出现在注释中,字符串中或者字符常量中。

2023-08-19 15:37:42 29

原创 第1章--快速上手

3、写一个程序从标准输入中读取字符之后在标准输出中写出,同时应该计算checksum并把它写在字符的后面,checksum用一个signed char变量计算并初始化为-1,每从标准输入读取一个字符,checksum的值就增加,checksum变量的值溢出部分忽略,当所有的字符被写入时,checksum作为一个整型数写出,它可能是个负数,确定在checksum的后面加个换行符,计算时使用ASCII码,如果运行你的程序时输入hello world!1、写一个程序,它打印出一行hello world!

2023-08-13 15:00:00 25

原创 第11章--网络编程

每个网络应用都是基于客户端-服务器模型的。采用这个模型,一个应用是由一个服务器进程和一个或者多个客户端进程组成。服务器管理某种资源,并且通过操作这种资源来为他的客户端提供某种服务。客户端-服务器模型中的基本操作是事务。一个客户端-服务器事务由以下四步组成。1)当一个客户端需要服务时,他向服务器发送一个请求,发起一个事务。2)服务器收到请求后,解释它,并以适当的方式操作它的资源。3)服务器给客户端发送一个响应,并等待下一个请求。4)客户端收到响应并处理它。

2023-08-08 17:23:28 32

原创 Git学习总结

Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

2023-08-06 14:00:00 26

原创 Makefile总结

Makefile中的变量实际上就是一个字符串。变量的名称可以由大小写字母、阿拉伯数字和下划线构成。至于值列表,既可以是零项,也可以是一项或者是多项。调用变量的时候可以用 “$(VALUE_LIST)” 或者是 “${VALUE_LIST}” 来引用。

2023-08-01 14:40:20 153

原创 第10章--系统级IO

标准I/O函数提供了Unix I/O函数的一个更加完整的带缓冲的替代品,包括格式化的I/O例程,如printf和scanf。这个库(libc)提供了打开和关闭文件的函数(fopen和fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs)、以及复杂的格式化的I/O函数(scanf和printf)。一个Linux文件就是一个m个字节的序列,所有的I/O设备都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。RIO提供了两类不同的函数。

2023-07-08 14:00:00 42

原创 第9章--虚拟内存

尽管在整个运行过程中程序引用的不同页面的总数可能超出物理内存总的大小,但是局部性原则保证了在任意时刻,程序将趋向于在一个较小的活动页面集合上工作,这个集合叫做工作集或者常驻集合。如果一个进程将一个共享对象映射到它的虚拟地址空间的一个区域内,那么这个进程对这个区域的任何写操作,对于那些也把这个共享对象映射到他们虚拟内存的其他进程而言,也是可见的。mmap函数要求内核创建一个新的虚拟内存区域,最好是从地址start开始的一个区域,并将文件描述符fd指定的对象的一个连续的片映射到这个新的区域。

2023-06-29 16:16:48 164

原创 第8章--异常控制流

在内核调度了一个新的进程运行后,它就抢占当前进程,并使用一种称为上下文切换的机制来将控制转移到新的进程,1)保存当前进程的上下文,2)回复某个先前被抢占的进程被保存的上下文,3)将控制传递给这个新恢复的进程。如果想用调试器单步执行程序,我们会看到一系列的程序计数器(PC)的值,这些值唯一的对应于包含在程序的可执行目标文件中的指令,或是包含在运行时动态链接到程序的共享对象中的指令。当父进程回收已终止的子进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程,从此刻开始,该进程就不存在了。

2023-06-21 16:00:00 49

原创 第7章--链接

在编译时,编译器向汇编器输出每个全局符号,或者是强或者是弱,而汇编器把这个信息隐含地编码在可重定位目标文件的符号表里。函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号。规则1:不允许有多个同名的强符号。规则2:如果有一个强符号和多个弱符号同名,那么选择强符号。规则3:如果有多个弱符号同名,那么从这些弱符号中任意选择一个。

2023-06-17 13:50:04 103

原创 第3章--程序的机器级表示

对于机器级编程来说,其中两种抽象尤为重要。第一种是由指令集体系结构或指令集架构来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。第二种抽象是,机器级程序使用的内存地址是虚拟地址,提供的内存模型看上去是一个非常大的字节数组。x86-64的机器代码和原始的C代码差别非常大。程序内存包括:程序的可执行机器代码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的内存块。一条机器指令只执行一个非常基本的操作。

2023-05-28 15:00:00 217

原创 第2章--信息的表示和处理

大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存。内存的每个字节都有一个唯一的数字来标识,称为它的地址,所有可能地址的集合就称为虚拟地址空间。

2023-05-24 15:30:06 26

原创 第1章--计算机系统漫游

系统中所有的信息–包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。比如,在不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。

2023-05-20 13:00:00 28

原创 第13章--Linux块设备驱动

所有的I/O请求都会先放入一个队列,统一由I/O调度层管理,它决定队列中的请求的排列顺序以及什么时候派发请求到块设备驱动,最终由块设备驱动程序操作到相关的硬件。块设备对于I/O请求有对应的缓冲区,可以调整响应顺序,而字符设备没有缓冲、直接读写。当这个结构代表一个块设备时,bd_disk成员指向设备的gendisk结构。块设备只能以块为单位接收输入和返回输出,而字符设备则以字节为单位。是连接抽象的块设备操作与具体块设备操作之间的枢纽。块设备可以随机访问,而字符设备只能顺序读写。

2023-05-17 09:45:24 57

原创 第12章--Linux设备驱动的软件架构思想

Linux设备驱动非常重视软件的可重用和跨平台能力。在Linux总线、设备和驱动模型中,驱动只管驱动,设备只管设备,总线则负责匹配设备和驱动,而驱动则以标准途径拿到板级信息。将软件进行分层设计应该是软件工程最基本的一个思想,如果提炼一个input的核心层出来,把跟Linux接口以及整个一套input事件的汇报机制都在这里面实现,显然是非常好的。在Linux设备驱动框架的设计中,除了有分层设计以外,还有分离的思想。

2023-05-14 15:30:00 250

原创 第11章--内存与IO访问

目前,大多数嵌入式微控制器中并不提供I/O空间,而仅存在内存空间。内存空间可以直接通过地址、指针来访问,程序及在程序运行中使用的变量和其他数据都存在于内存空间中。

2023-05-11 14:48:29 272

原创 第10章--中断与时钟

所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停当前程序的执行,转去处理突发事件,处理完毕后又返回原程序被中断的位置继续执行。根据中断的来源,中断可分为内部中断和外部中断,内部中断来自CPU内部(软件中断指令、溢出、除法错误等),外部中断来自CPU外部,由外设提出请求。根据中断是否可以屏蔽,中断可分为可屏蔽中断和不可屏蔽中断,可屏蔽中断可以通过设置中断控制器寄存器等方法被屏蔽,屏蔽后,该中断不再得到响应,而不可屏蔽中断不能被屏蔽。

2023-05-07 14:30:00 298

原创 第9章--异步通知与异步IO

异步通知的意思是:一旦设备就绪,则主动通知应用程序,这一点非常类似于硬件上“中断”的概念。信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

2023-05-04 10:09:46 271

原创 第8章--阻塞与非阻塞IO

阻塞操作是指在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作。被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。而非阻塞操作的进程在不能进行设备操作时,并不挂起,他要么放弃,要么不停地查询,直到可以进行操作为止。

2023-04-30 16:00:00 30

原创 第7章--并发控制

并发指的是多个执行单元同时、并行被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态。在Linux内核中,主要的竞态发生于如下几种情况。解决竞态问题的途径是保证对共享资源的互斥访问,即一个执行单元在访问共享资源的时候,其他的执行单元被禁止访问。

2023-04-25 14:00:00 34

原创 第6章--字符设备驱动

file_operations结构体中的成员函数是字符设备驱动程序设计的主题内容,这些函数实际会在应用程序进行Linux的open()、write()、read()、close()等系统调用时最终被内核调用。

2023-04-22 14:00:00 100

原创 第5章--文件系统与设备文件

创建参数mode指定新建文件的存取权限,它同umask一起决定文件的最终权限(mode&umask)。打开open函数有两个形式,其中pathname是我们要打开的文件名,flags指定打开的方式。读写参数buf为指向缓冲区的指针,length为缓冲区的大小(以字节为单位)。函数read实现从文件描述符fd所指定的文件中读取length个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。

2023-04-18 10:08:50 82

原创 第4章--Linux内核模块

Linux提供了这样的机制,这种机制被称为模块(Module)。模块具有这样的特点。

2023-04-10 10:52:14 104 1

原创 第3章--Linux内核及内核编程

arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录。/block:块设备驱动程序I/O调度。/crypto:常见加密和散列算法,以及一些压缩和CRC校验算法。/documentation:内核各部分的通用解释和注释。/drivers:设备驱动程序,每个不同的驱动占用一个子目录。/fs:所支持的各种文件系统。/include:头文件。/init:内核初始化代码。/ipc:进程间通信的代码。/kernel:内核最核心的部分,包括进程调度、定时器等。

2023-04-06 10:14:52 291 1

原创 第2章--驱动设计的硬件基础

目前主流的通用处理器多采用 SoC(片上系统)的芯片设计方法,集成了各种功能模块,每一种功能都是由硬件描述语言设计程序,然后在 SoC 内由电路实现的。中央处理器的体系结构可以分为两类,一类为冯·诺依曼结构,另一类为哈佛结构。冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,因此程序指令和数据的宽度相同。而哈佛结构将程序指令和数据分开存储,指令和数据可以有不同的数据宽度。

2023-04-03 15:24:31 195 1

原创 第1章--Linux设备驱动概述

任何一个计算机系统的运转都是系统中软硬件共同努力的结果。对设备驱动最通俗的解释就是“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮询、中断处理、DMA 通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。由此可见,设备驱动充当了硬件和应用软件之间的纽带,应用软件时只需要调用系统软件的应用编程接口(API)就可让硬件去完成要求的工作。

2023-04-03 10:41:52 106 2

空空如也

空空如也

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

TA关注的人

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