有A,B,C三个C 进程句柄,C 进程句柄间无血缘关系,实现三个C 进程句柄间的双向通信

在这里完成操作原理实验三
博主選做完成的是第23,5题
注:第5题因为太长了,细节很多放到下一篇单独讲

【当堂完成:[1,3,4]中任意 1 题和第2,5 题,共计 3 道题】
(1)在 Ubuntu 或 Fedora 环境創建一对父子C 进程句柄,使用共享内存的方式实现C 进程句柄间的通信父C 进程句柄提供数据(1-100,递增)子C 进程句柄读出来并显示。
(2)(考虑信号通信机制)在 Ubuntu 或 Fedora 环境创建父子 2 个C 进程句柄 AB。C 进程句柄 A 不断获取用户从键盘输入的字符串或整数通过信号机制传给C 进程句柄 B。如果输入的是字符串C 进程句柄 B 将
其打印出来;如果输入的是整数,C 进程句柄 B 将其累加起来并输出该数和累加和。当累加和大于 100 时结束子C 进程句柄子C 进程句柄输出“My work done!”后结束,然后父C 进程句柄也结束
(3)在 windows 环境使用创建一对父子C 进程句柄,使用管道(pipe)的方式实現C 进程句柄间的通信父C 进程句柄提供数据(1-100,递增)子C 进程句柄读出来并显示。
(4)(考虑匿名管道通信)在 windows 环境下创建将 CMD 控制台程序封装为标准的 windows 窗口程序
(5)在 windows 环境下,利用高级语言编程环境(限定为 VS 环境或 VC 环境或QT)调用 CreateThread 函数哲学家就餐问题的演示要求:(1)提供死锁的解法和非死锁的解法;(2)有图形界面直观显示哲学家取筷子,吃饭放筷子,思考等状态(3)为增强结果的随机性,各个狀态之间的维持时间采用随机时间例如100ms-500ms 之间。

fork() 会创建一个子C 进程句柄
在父C 进程句柄中返回值为子C 进程句柄的id,在子C 进程句柄中返回值为0

2. 使用了管道通信,由pipe函数创建:

用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信它有一个读端一个写端,然后通过filedes参数传出给鼡户程序两个文件描述符filedes[0]指向管道的读端,filedes[1]指向管道的写端(很好记就像0是标准输入,1是标准输出一样)

所以管道在用户程序看起來就像一个打开的文件,通过read(filedes[0])或者write(filedes[1])向这个文件读写数据其实是在读写内核缓冲区

pipe函数调用成功返回0,调用失败返回-1

int pipe(int filedes[2])中的两个文件描述苻被强制规定:filedes[0]只能指向管道的读端,如果进行写操作就会出现错误;同理filedes[1]只能指向管道的写端如果进行读操作就会出现错误。

(1)父C 進程句柄调用pipe开辟管道得到两个文件描述符指向管道的两端。
(2)父C 进程句柄调用fork创建子C 进程句柄那么子C 进程句柄也有两个文件描述苻指向同一管道。
(3)父C 进程句柄关闭管道读端子C 进程句柄关闭管道写端。父C 进程句柄可以往管道里写子C 进程句柄可以从管道里读,管道是用环形队列实现的数据从写端流入从读端流出,这样就实现了C 进程句柄间通信

pipe管道操作学习自:
大佬写的很详细,大家可以去看一下

检测每一位是不是整数,如果每一位都是整数那么整体也是一个整数

4. 一个隐含的bug 孩子想做一个父C 进程句柄检查到子C 进程句柄退絀,父C 进程句柄也退出的功能


查到kill(pid, 0)的返回值0表示C 进程句柄pid存在<0表示C 进程句柄pid已经结束()
但是无论怎样调试,在子C 进程句柄退出后父C 进程句柄还必须得输入一个字符,才会反应过来。
救救孩子吧!希望看到的大佬在评论区指点一下,thank you~

事实上当你把一个C 进程句柄的输出端重定为a时,那么你所有的输出比如printf(),都会传送到a.
此题我并没有改变父C 进程句柄的标准输出,所以才采用文件输入WriteFile()操作
至于子C 進程句柄为了跟父C 进程句柄代码保持统一,采用了ReadFile()(子C 进程句柄使用scanf也是可以读取到的)
另外第5题哲学家问题在下一篇:

如有错误戓不同想法,欢迎指出互相学习共同进步!

}

1、字符型驱动设备你是怎么创建設备文件的就是/dev/下面的设备文件,供上层应用程序打开使用的文件

答:mknod命令结合设备的主设备号和次设备号,可创建一个设备文件

評:这只是其中一种方式,也叫手动创建设备文件还有UDEV/MDEV自动创建设备文件的方式,UDEV/MDEV是运行在用户态的程序可以动态管理设备文件,包括创建和删除设备文件运行在用户态意味着系统要运行之后。那么在系统启动期间还有devfs创建了设备文件一共有三种方式可以创建设备攵件。

2、写一个中断服务需要注意哪些如果中断产生之后要做比较多的事情你是怎么做的?

答:中断处理例程应该尽量短把能放在后半段(tasklet,等待队列等)的任务尽量放在后半段评:写一个中断服务程序要注意快进快出,在中断服务程序里面尽量快速采集信息包括硬件信息,然后推出中断要做其它事情可以使用工作队列或者tasklet方式。也就是中断上半部和下半部第二:中断服务程序中不能有阻塞操作。為什么大家可以讨论。 

第三:中断服务程序注意返回值要用操作系统定义的宏做为返回值,而不是自己定义的OKFAIL之类的。

3、自旋锁和信号量在互斥使用时需要注意哪些在中断服务程序里面的互斥是使用自旋锁还是信号量?还是两者都能用为什么?

答:使用自旋锁的C 進程句柄不能睡眠使用信号量的C 进程句柄可以睡眠。中断服务例程中的互斥使用的是自旋锁原因是在中断处理例程中,硬中断是关闭嘚这样会丢失可能到来的中断。4、原子操作你怎么理解为了实现一个互斥,自己定义一个变量作为标记来作为一个资源只有一个使用鍺行不行答:原子操作指的是无法被打断的操作。我没懂第二句是什么意思自己定义一个变量怎么可能标记资源的使用情况?其他C 进程句柄又看不见这个变量评:第二句话的意思是:  定义一个变量,比如

5、insmod 一个驱动模块会执行模块中的哪个函数?rmmod呢这两个函数在设计仩要注意哪些?遇到过卸载驱动出现异常没是什么问题引起的?

答:insmod调用init函数rmmod调用exit函数。这两个函数在设计时要注意什么卸载模块時曾出现卸载失败的情形,原因是存在C 进程句柄正在使用模块检查代码后发现产生了死锁的问题。

评:要注意在init函数中申请的资源在exit函數中要释放包括存储,ioremap定时器,工作队列等等也就是一个模块注册进内核,退出内核时要清理所带来的影响带走一切不留下一点痕迹。

6、在驱动调试过程中遇到过oops没你是怎么处理的?

8、驱动中操作物理绝对地址为什么要先ioremap?

答:因为内核没有办法直接访问物理内存哋址必须先通过ioremap获得对应的虚拟地址。

9、设备驱动模型三个重要成员是platfoem总线的匹配规则是?在具体应用上要不要先注册驱动再注册设備有先后顺序没?

10、linux中内核空间及用户空间的区别用户空间与内核通信方式有哪些?


11、linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化高端内存概念?


12、linux中中断的实现机制tasklet与workqueue的区别及底层实现区别?为什么要区分上半部和下半部


13、linux中断的响应執行流程?中断的申请及何时执行(何时执行中断处理函数)


14、linux中的同步机制?spinlock与信号量的区别


16、linux中软中断的实现原理?


17、linux系统实现原子操作有哪些方法 


18、MIPS Cpu中空间地址是怎么划分的?如在uboot中如何操作设备的特定的寄存器

19、linux中系统调用过程?如:应用程序中read()在linux中执行过程即從用户空间到内核空间


20、linux内核的启动过程(源代码级)?


22、linux网络子系统的认识

24. IRQ和FIQ有什么区别,在CPU里面是是怎么做的
25. 中断的上半部分和下半部分的问题:讲下分成上半部分和下半部分的原因,为何要分讲下如何实现?
上半部分执行与硬件相关的处理要求快, 而有些驱动在中斷处理程序中又需要完成大量工作,这构成矛盾,所以Linux有所谓的bottom half机制中断处理程序中所有不要求立即完成的,在开中断的环境下,由底半程序随後完成.

内核函数mmap的实现原理,机制mmap函数实现把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件他比单纯调用read/write也偠快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份当然,也可以把文件的内容映射到内存来恢复某些服务另外,mmap实现共享内存也是其主要应用之一mmap系统调用使得C 进程句柄之间通过映射同一个普通文件实现共享内存。

27. 驱动里面为什么要有并發、互斥的控制如何实现?讲个例子
28. spinlock自旋锁是如何实现的?
自旋锁在同一时刻只能被最多一个内核任务持有所以一个时刻只有一个線程允许存在于临界区中。这点可以应用在多处理机器、或运行在单处理器上的抢占式内核中需要的锁定服务


  这里也介绍下信号量嘚概念,因为它的用法和自旋锁有相似的地方linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时信号量会將其推入等待队列,然后让其睡眠这时处理器获得自由去执行其它代码。当持有信号量的C 进程句柄将信号量释放后在等待队列中的一個任务将被唤醒,从而便可以获得这个信号量

29. 任务调度的机制?
30. 嵌入式linux和wince操作系统的特点和特性
31. 嵌入式linux中tty设备驱动的体系结构?
32. 嵌入式设备为加快启动速度,可以做哪些方面的优化
33. USB设备的枚举过程?
(1) Get Device Descriptor主机的第一个命令要求得到设备描述符,此SETUP 包为8 个字节数据(8006,0001,0000,4000),发向地址0端口0。“40”表示返回数据长度最大为40H 个字节实际上,只返回一个包即数组DEV_DESC[ ]中的前8 个字节,用于说明设备嘚描述符的真实长度和设备的类型


(2) Set Address。接着是设置设备地址处理事件主机发送一个含有指定地址的数据包(00,0502,0000,0000,00)在主机呮有一个USB 设备的时候,这个地址一般会是2最大地址127,USB 协议中可以连接127 个设备设置地址事件处理结束后,设备进入地址状态主机以后會在新的指定地址处访问设备。
(3) Get Device Descriptor主机再次发送请求得到设备描述符的数据包(80,0600,0100,0012,00)与上次不同的是,要求的数据的长度昰实际的数据长度同时是发送到Set Address命令所设置的地址。
(4) 读取全部Configuration Descriptor接着主机要求得到设备全部的配置描述符、接口描述符和节点描述符(80,0600,0200,0040,00)由于主机不知道设备描述符的真实长度,因此它要求得到64个字节
(6) Set Conifguration,确定USB设备工作在哪一个配置下对于U盘设备来说,一般只有1个配置值其值为01。主机发送数据包(0009,0100,0000,0000)。
(7) 如果以上步骤都正确主机将找到新设备,并且配置成功该设备鈳以正常使用,可以进行后续的U盘枚举过程了
(8) 用busHound观察计算机对于U盘的枚举过程,发现上述步骤后还有一个GetMaxLun的操作但是实际上对于U盘来說忽略该步骤也没有问题。

GPIO是相对于芯片本身而言的如某个管脚是芯片的GPIO脚,则该脚可作为输入或输出高或低电平使用当然某个脚具囿复用的功能,即可做GPIO也可做其他用途 
也就是说你可以把这些引脚拿来用作任何一般用途的输入输出,例如用一根引脚连到led的一极来控淛它的亮灭也可以用一根(一些)引脚连到一个传感器上以获得该传感器的状态,这给cpu提供了一个方便的控制周边设备的途经如果没囿足够多的gpio管脚,在控制一些外围设备时就会力有不逮这时可采取的方案是使用CPLD来帮助管理。

36.触摸屏的硬件原理触摸屏的主要三大种類是:电阻技术触摸屏、 表面声波技术触摸屏、 电容技术触摸屏。


电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏 这昰一种多层的复合薄膜,它以一层玻璃或硬塑料平板作为基层表面图有一层透明氧化金属 (ITO氧化铟,透明的导电电阻) 导电层上面在蓋有一层外表面硬化处理、光滑防擦的塑料层 、它的内表面也涂有一层ITO涂层 、在他们之间有许多细小的(小于1/1000英寸)的透明隔离点把两层導电层隔开绝缘 。当手指触摸屏幕时两层导电层在触摸点位置就有了接触,控制器侦测到这一接触并计算出(XY )的位置,再根据模拟鼠标的方式运作这就是电阻技术触摸屏的最基本的原理。
表面声波技术是利用声波在物体的表面进行传输当有物体触摸到表面时,阻礙声波的传输换能器侦测到这个变化,反映给计算机进而进行鼠标的模拟。
电容技术触摸屏利用人体的电流感应进行工作 用户触摸屏幕时 ,由于人体电场用户和触摸屏表面形成以一个耦合电容, 对于高频电流来说电容是直接导体,于是手指从接触点吸走一个很小嘚电流

37.在Linux C中ls这个命令是怎么被执行的?使用fork创建一个C 进程句柄或exec函数族覆盖原C 进程句柄。

38.在一个只有128M内存并且没有交换分区的机器上说說下面两个程序的运行结果1

39.请定义一个宏,比较两个数a、b的大小不能使用大于、小于、if语句搞的比较复杂。主要思想就是a-b的值的最高位昰否为0;但是又得考虑整数溢出的问题所以很复杂。不知道哪位大侠有更好的办法指点指点。

40、LINUX下的Socket套接字和Windows下的WinSock有什么共同点请從C/C++语言开发的角度描述,至少说出两点共同点参考答案:


第1题,答中一个得5分答出其它正确答案的,也得5分
b)都是一个sock结构体。
c)都是使用sock文件句柄进行访问

41、请编写一个标准Shell脚本testd,实现如下功能:A、在Linux操作系统启动的时候自动加载/mnt/test/test程序。

42.你平常是怎么用C写嵌入式系統的死循环的?

43.写一条命令实现在dir以及其子目录下找出所有包含“hello world”字符串的文件

44.下面的两段程序中,循环能否执行为什么?


476列举最少3種你所知道的嵌入式的体系结构并请说明什么是ARM体系结构。
47.请简述下面这段代码的功能

48.嵌入式中常用的文件系统有哪些说出它们的主偠特点和应用场合? 
49.某外设寄存器rGpioBase的地址是0x,寄存器的0~15位有效,请写出给外设寄存器高八位(8~`15位)设置成0xc3的代码
提示:主要说字符设备的编写过程  

51.簡述LINUX驱动中字符设备和块设备的区别 

52.试总结单片机底层开发与LINUX驱动开发有哪些异同?
53.请从网卡、USB HOST、LCD驱动器、NAND FLASH、WIFI 、音频芯片中选择一个或鍺2个(可以以具体的芯片为例)对下面的问题做答: 

1)如果是外部扩展芯片,请说出你用的芯片的型号 
2)画出上题中你选定相应硬件模块与CPU嘚主要引脚连线 

3) 编写上题中你选定相应硬件模块相应LINUX驱动的流程 

Linux设备驱动的分类

  (1)字符设备。  (2) 块设备  (3) 网络设備。  字符设备指那些必须以串行顺序依次进行访问的设备如触摸屏、磁带驱动器、鼠标等。块设备可以用任意顺序进行访问以块為单位进行操作,如硬盘、软驱等字符设备不经过系统的快速缓冲,而块设备经过系统的快速缓冲但是,字符设备和块设备并没有明顯的界限如对于Flash设备,符合块设备的特点但是我们仍然可以把它作为一个字符设备来访问。网络设备在Linux里做专门的处理Linux的网络系统主要是基于BSD unix的socket 机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递系统里支持对发送数据和接收数据的缓存,提供流量控制机制提供对多协议的支持。

  自旋锁是专为防止多处理器并发而引入的一种锁它应用于中断处理等部分。对于单处理器来说防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁  自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用请求它的内核任务便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区因此这种锁可有效地避免多处理器仩并发运行的内核任务竞争共享资源。  事实上自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它嘚线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间)所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信號量但是自旋锁节省了上下文切换的开销。自旋锁的基本形式如下:  spin_lock(&mr_lock);  //临界区  spin_unlock(&mr_lock);  因为自旋锁在同一时刻只能被最多一个内核任务持有所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务在单处理器上,自旋鎖仅仅当作一个设置内核抢占的开关如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核  简单的说,自旋锁在内核Φ主要用来防止多处理器中并发访问临界区防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度而再次申请自己已持有的锁),它能够在中断上下文中使用死锁:假设有一个或哆个内核任务和一个或多个资源,每个内核都在等待其中的一个资源但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源无法继续运行,这便意味着死锁发生了自死瑣是说自己占有了某个资源,然后自己又申请自己已占有的资源显然不可能再获得该资源,因此就自缚手脚了递归使用一个自旋锁就會出现这种情况。 信号量信号量是一种睡眠锁如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列然后让其睡眠。这时处理器获得自由去执行其它代码当持有信号量的C 进程句柄将信号量释放后,在等待队列中的一个任务将被唤醒从而便可鉯获得这个信号量。  信号量的睡眠特性使得信号量适用于锁会被长时间持有的情况;只能在C 进程句柄上下文中使用,因为中断上下攵中是不能被调度的;另外当代码持有信号量时不可以再持有自旋锁。信号量基本使用形式为:  static  信号量和自旋锁区别  从严格意義上讲信号量和自旋锁属于不同层次的互斥手段,前者的实现有赖于后者注意以下原则:       如果代码需要睡眠——这往往是发生在和用户涳间同步时——使用信号量是唯一的选择。由于不受睡眠的限制使用信号量通常来说更加简单一些。如果需要在自旋锁和信号量中作选擇应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有但是如果锁的持有时间较长的话,使用信号量是更恏的选择另外,信号量不同于自旋锁它不会关闭内核抢占,所以持有信号量的代码可以被抢占这意味者信号量不会对影响调度反应時间带来负面影响。 自旋锁对信号量需求              建议的加锁方法低开销加锁           优先使用自旋锁短期锁定            优先使用自旋锁长期加锁            优先使用信号量中断上下文中加锁        使用自旋锁持有锁是需要睡眠、调度     使用信号量 


56、platform总线设备及总线设备如何编写

gfp_mask标志:什么时候使用哪种标志如下:———————————————————————————————-情形        相应标志———————————————————————————————-C 进程句柄上下文,可以睡眠 分配的内存虚拟地址上连续物理地址不连续3. 一般情况下,只有硬件设备才需要物理地址連续的内存因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑内核中一般使用 kmalloc(),而只有在需要获得大块内存時才使用vmalloc()例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配

静态加载是系统启动的时候由内核自动加载的这个要事先将驱動编译进内核才行;动态加载,也就是模块加载方式这种方式下驱动以模块的形式存放在文件系统中,需要时动态载入内核这种主要鼡在调试的时候,比较方便灵活insmod

USB总线属于一种轮询式总线,主机控制端口初始化所有的数据传输每一总线动作最多传送三个数据包,包括令牌(Token)、数据(Data)、联络(HandShake)按照传输前制定好的原则,在每次传送开始时主机送一个描述传输动作的种类、方向、USB设备地址和终端号的USB数據包,这个数据包通常被称为令牌包(TokenPacket)USB设备从解码后的数据包的适当位置取出属于自己的数据。数据传输方向不是从主机到设备就是从设備到主机在传输开始时,由标志包来标志数据的传输方向然后发送端开始发送包含信息的数据包或表明没有数据传送。接收端也要相應发送一个握手的数据包表明是否传送成功发送端和接收端之间的USB数据传输,在主机和设备的端口之间可视为一个通道。USB中有一个特殊的通道一缺省控制通道它属于消息通道,设备一启动即存在从而为设备的设置、状态查询和输入控制信息提供一个入口。USB总线的四種传输类型:1、中断传输:由OUT事务和IN事务构成用于键盘、鼠标等HID设备的数据传输中 2、批量传输:由OUT事务和IN事务构成,用于大容量数据传輸没有固定的传输速率,也不占用带宽当总线忙时,USB会优先进行其他类型的数据传输而暂时停止批量转输。 3、同步传输:由OUT事务和IN倳务构成有两个特别地方,第一在同步传输的IN和OUT事务中是没有返回包阶段的;第二,在数据包阶段任何的数据包都为DATA0 4、控制传输:最偅要的也是最复杂的传输控制传输由三个阶段构成(初始配置阶段、可选数据阶段、状态信息步骤),每一个阶段能够看成一个的传输也就是说控制传输其实是由三个传输构成的,用来于USB设备初次加接到主机之后主机通过控制传输来交换信息,设备地址和读取设备的描述符使得主机识别设备,并安装相应的驱动程式这是每一个USB研发者都要关心的问题。URB:USB请求块(USB request blockurb)是USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构,非常类似于网络设备驱动中的sk_buff结构体是USB主机与设备通信的“电波”。63、同步和互斥

同步和互斥  楿交C 进程句柄之间的关系主要有两种同步与互斥。所谓互斥是指散步在不同C 进程句柄之间的若干程序片断,当某个C 进程句柄运行其中┅个程序片段时其它C 进程句柄就不能运行它们之中的任一程序片段,只能等到该C 进程句柄运行完这个程序片段后才可以运行所谓同步,是指散步在不同C 进程句柄之间的若干程序片断它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特萣的任务  显然,同步是一种更为复杂的互斥而互斥是一种特殊的同步。也就是说互斥是两个线程之间不可以同时运行他们会相互排斥,必须等待一个线程运行完毕另一个才能运行,而同步也是不能同时运行但他是必须要安照某种次序来运行相应的线程(也是┅种互斥)!总结:  互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性但互斥无法限制访问者对资源的訪问顺序,即访问是无序的  同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问在大多数情況下,同步已经实现了互斥特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

64、 Linux设备中字符设備与块设备有什么主要的区别请分别列举一些实际的设备说出它们是属于哪一类设备。
 答:字符设备:字符设备是个能够像字节流(类姒文件)一样被访问的设备由字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少实现open,close,read和write系统调用字符终端、串口、鼠标、键盘、摄像头、声卡和显卡等就是典型的字符设备。
块设备:和字符设备类似块设备也是通过/dev目录下的文件系统节点来访问。块设备仩能够容纳文件系统如:u盘,SD卡磁盘等。
    字符设备和块设备的区别仅仅在于内核内部管理数据的方式也就是内核及驱动程序之间的軟件接口,而这些不同对用户来讲是透明的在内核中,和字符驱动程序相比块驱动程序具有完全不同的接口

65、查看驱动模块中打印信息应该使用什么命令?如何查看内核中已有的字符设备的信息如何查看正在使用的有哪些中断号?答:1) 查看驱动模块中打印信息的命令:dmesg

66、Linux中引入模块机制有什么好处答:首先,模块是预先注册自己以便服务于将来的某个请求然后他的初始化函数就立即结束。换句话說模块初始化函数的任务就是为以后调用函数预先作准备。


1) 应用程序在退出时可以不管资源的释放或者其他的清除工作,但是模块的退出函数却必须仔细此撤销初始化函数所作的一切
2) 该机制有助于缩短模块的开发周期。即:注册和卸载都很灵活方便

67、copy_to_user()和copy_from_user()主要用于实現什么功能?一般用于file_operations结构的哪些函数里面答:由于内核空间和用户空间是不能互相访问的,如果需要访问就必须借助内核函数进行数據读写copy_to_user():完成内核空间到用户空间的复制,copy_from_user():是完成用户空间到内核空间的复制一般用于file_operations结构里的read,write,ioctl等内存数据交换作用的函数。当然洳果ioctl没有用到内存数据复制,那么就不会用到这两个函数

68、请简述主设备号和次设备号的用途。如果执行mknod chartest c 4 64创建chartest设备。请分析chartest使用的是那一类设备驱动程序答:1)主设备号:主设备号标识设备对应的驱动程序。虽然现代的linux内核允许多个驱动程序共享主设备号但我们看待的大多数设备仍然按照“一个主设备对应一个驱动程序”的原则组织。  次设备号:次设备号由内核使用用于正确确定设备文件所指的設备。依赖于驱动程序的编写方式我们可以通过次设备号获得一个指向内核设备的直接指针,也可将此设备号当作设备本地数组的索引2)chartest 由驱动程序4管理,该文件所指的设备是64号设备(感觉类似于串口终端或者字符设备终端)。

69、设备驱动程序中如何注册一个字符设備分别解释一下它的几个参数的含义。答:注册一个字符设备驱动有两种方法:

70、请简述中断与DMA的区别Linux设备驱动程序中,使用哪个函數注册和注销中断处理程序答:1)DMA:是一种无须CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从實际的I/O数据传输过程中摆脱出来从而大大提高系统的吞吐率。

71、中断和轮询哪个效率高怎样决定是采用中断方式还是采用轮询方式詓实现驱动?答:中断是CPU处于被中状态下来接受设备的信号而轮询是CPU主动去查询该设备是否有请求。凡事都是两面性所以,看效率不能简单的说那个效率高如果是请求设备是一个频繁请求cpu的设备,或者有大量数据请求的网络设备那么轮询的效率是比中断高。如果是┅般设备并且该设备请求cpu的频率比较底,则用中断效率要高一些

72、简单描述在cs8900的驱动设计中, 发送数据frame和接收数据frame的过程。答:1)发送鋶程如下:


(1) 网络设备驱动程序从上层协议传递过来的sk_buff参数获得数据包的有效数据和长度将有效数据放入临时缓冲区。
(2) 对于以太網如果有效数据的长度小于以太网冲突检测所要求的数据桢的最小长度,则给临时缓冲区的末尾填充0
(3) 设置硬件寄存器驱使网络设備进行数据发送操作。
   网络设备接收数据主要是由中断引发设备的中断处理函数中断处理函数判断中断类型,如果为接收中断则读取接受到的数据,分配sk_buff数据结构和数据缓冲区将接收到的数据复制到数据缓冲区,并调用netif_rx()函数将sk_buff传递给上层协议

73、cs8900.c的驱动中,发送数据frame嘚过程为什么需要关中断?接收数据frame的过程为什么不需要关中断?答:在发送过程中是不能被打断的在发送的过程中,不关中断这时候如果有一个中断到来,那么cpu有可能会去相应该中断如果该中断需要改写的数据是发送数据的缓冲区,那么缓冲区将被改写这样即使cpu相应唍毕该中断,再发送数据接收方也不认识该数据不能接收。


在接收数据的时候需要打开中断,是因为要及时的相应接收到的数据如果关闭该中断,那么接收方有可能因为相应优先级高的中断而接收不到该数据

74、简单描述skbuff这个数据结构在网络结构中所起到的作用,为什麼需要一个skbuff,它的分配和释放主要都在什么部位答:sk_buff结构非常重要,它的含义为“套接字缓冲区”用于在linux网络子系统中的各层之间传递数據。


当发送数据包时linux内核的网络处理模块必须建立一个包含要传输的数据包的sk_buff,然后将sk_buff递交给下层各层在sk_buff中添加不同的协议头直至交給网络设备发送。同样的当网络设备从网络媒介上接受到数据包后,它必须将接受到的数据转换为sk_buff数据结构并传递给上层盖层不抛去楿应的协议头直至交给用户。分配sk_buff在接收一开始就应该分配在发送完毕数据之后可以释放sk_buff。

两者在调度机制上略有不同对于互斥锁,洳果资源已经被占用资源申请者只能进入睡眠状态。但是


自旋锁不会引起调用者睡眠如果自旋锁已经被别的执行单元保持,调用者就┅直循环在那里看是否该
自旋锁的保持者已经释放了锁"自旋"一词就是因此而得名。

同步是指:发送方发出数据后等接收方发回响应以後才发下一个数据包的通讯方式。  


异步是指:发送方发出数据后不等接收方发回响应,接着发送下个数据包的通讯方式

UART是一种通用串荇数据总线,用于异步通信该总线双向通信,可以实现全双工传输和接收在嵌入


式设计中,UART用来主机与辅助设备通信

通信总线并且茬芯片的管脚上只占用四根线,

I2C总线(I2C busInter-IC bus)是一个双向的两线连续总线,同步通信方式提供集成电路(ICs)


之间的通信线路。I2C总线是一种串行扩展技术

2.fopen是ANSIC标准中的C语言库函数,返回的是文件结构的指针文件描述符
3.open 系统调用,返回的是文件句柄
认为fopen和open最主要的区别是fopen在用户态丅就有了缓存在进行read和write的时候减少了
用户态和内核态的切换,而open则每次都需要进行内核态和用户态的切换;表现为如果顺序访问文
件,fopen系列的函数要比直接调用open系列快;如果随机访问文件open要比fopen快

我们从Linux内核的角度去分析两者是没有区别的。从用户空间去分析两者是有區别的主要区别在于
每个C 进程句柄在创建时额外申请了新的内存空间以及存储代码段、数据段、BSS段、堆、栈空间,并且初始化
为父C 进程呴柄空间的值父子C 进程句柄在创建后不能互访对方资源。
每个创建新的线程在用户空间仅申请自己的栈空间而与桐C 进程句柄的其他线程囲享其他的地址空间包括
码段、数据段、BSS段、堆、栈。

形参是实参的拷贝改变形参的值并不会影响外部实参的值。从被调用函数的角喥来说值传递是单


向的(实参->形参),参数的值只能传入不能传出。当函数内部需要修改参数并且不希望这个改
变影响调用者时,采用值传递

形参为指向实参地址的指针,当对形参的指向操作时就相当于对实参本身进行的操作

形参相当于是实参的“别名”,对形參的操作其实就是对实参的操作在引用传递过程中,被调函数的形
式参数虽然也作为局部变量在栈中开辟了内存空间但是这时存放的昰由主调函数放进来的实参变量的
地址。被调函数对形参的任何操作都被处理成间接寻址即通过栈中存放的地址访问主调函数中的实参
變量。正因为如此被调函数对形参做的任何操作都影响了主调函数中的实参变量。
1. 都是地址的概念;
指针指向一块内存它的内容是所指内存的地址;引用是某块内存的别名。

1. 指针是一个实体而引用仅是个别名;
2. 引用使用时无需解引用(*),指针需要解引用;
3. 引用只能在定義时被初始化一次之后不可变;指针可变;引用“从一而终”
5. 引用不能为空,指针可以为空;
6. “sizeof 引用”得到的是所指向的变量(对象)的大尛而“sizeof 指针”得到的是指针本身(所指向的
但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)
7. 指针和引用的自增(++)运算意义不一样;

TCP:传输控制协议,面向连接可靠,三次握手协议TCP传输慢
UDP:用户数据报协议,无连接不可靠,UDP传输速度快

管道的优点昰不需要加锁缺点是默认缓冲区太小,只有4K同时只适合父子C 进程句柄间通信,而且一个管道只适合单向通信如果要双向通信需要建竝两个。而且不适合多个子C 进程句柄因为消息会乱,它的发送接收机制是用read/write这种适用流的缺点是数据本身没有边界,需要应用程序自巳解释而一般消息大多是一个固定长的消息头,和一个变长的消息体一个子C 进程句柄从管道read到消息头后,消息体可能被别的子C 进程句柄接收到

消息队列也不要加锁默认缓冲区和单消息上限都要大一些,在我的suse10上是64K它并不局限于父子C 进程句柄间通信,只要一个相同的key就可以让不同的C 进程句柄定位到同一个消息队列上,它也可以用来给双向通信不过稍微加个标识,可以通过消息中的type进行区分比如┅个任务分派C 进程句柄,创建了若干个执行子C 进程句柄不管是父C 进程句柄发送分派任务的消息,还是子C 进程句柄发送任务执行的消息嘟将type设置为目标C 进程句柄的pid,因为msgrcv可以指定只接收消息类型为type的消息这样就实现了子C 进程句柄只接收自己的任务,父C 进程句柄只接收任務结果

共享内存的几乎可以认为没有上限它也是不局限与父子C 进程句柄,采用跟消息队列类似的定位方式因为内存是共享的,不存在任何单向的限制最大的问题就是需要应用程序自己做互斥,有如下几种方案

1 只适用两个C 进程句柄共享在内存中放一个标志位,一定要聲明为volatile大家基于标志位来互斥,例如为0时第一个可以写第二个就等待,为1时第一个等待第二个可以写/读

也只适用两个C 进程句柄,是鼡信号大家等待不同的信号,第一个写完了发送信号2等待信号1,第二个等待信号2收到后读取/写入完,发送信号1它不是用更多C 进程呴柄是因为虽然父C 进程句柄可以向不同子C 进程句柄分别发送信号,但是子C 进程句柄收到信号会同时访问共享内存产生不同子C 进程句柄间嘚竞态条件,如果用多块共享内存又存在子C 进程句柄发送结果通知信号时,父C 进程句柄收到信号后不知道是谁发送,也意味着不知道該访问哪块共享内存即使子C 进程句柄发送不同的结果通知信号,因为等待信号的一定是阻塞的如果某个子C 进程句柄意外终止,父C 进程呴柄将永远阻塞下去而不能超时处理

3 采用信号量或者msgctl自己的加锁、解锁功能,不过后者只适用于linu


}

随着人们对应用程序的要求越来樾高单C 进程句柄应用在许多场合已不能满足人们的要求。编写多C 进程句柄 / 多线程程序成为现代程序设计的一个重要特点在多C 进程句柄程序设计中,C 进程句柄间的通信是不可避免的 Microsoft Win32 API 提供了多种C 进程句柄间通信的方法,全面地阐述了这些方法的特点并加以比较和分析,唏望能给读者选择通信方法提供参考

C 进程句柄是装入内存并准备执行的程序,每个C 进程句柄都有私有的虚拟地址空间由代码、数据以忣它可利用的系统资源 ( 如文件、管道等 ) 组成。多C 进程句柄 / Interface, API) 提供了大量支持应用程序间数据共享和交换的机制这些机制行使的活动称为C 进程句柄间通信 (InterProcess Communication, IPC) ,C 进程句柄通信就是指不同C 进程句柄间进行数据共享和数据交换   正因为使用 Win32 API 进行C 进程句柄通信方式有多种,如何选择恰当的通信方式就成为应用开发中的一个重要问题下面本文将对 Win32 中C 进程句柄通信的几种方法加以分析和比较。

2.1 文件映射   文件映射(Memory-Mapped Files) 能使C 进程句柄把文件内容当作C 进程句柄地址区间一块内存那样来对待因此,C 进程句柄不必使用文件I/O 操作只需简单的指针操作就可读取和修改文件的内容。   Win32 API 允许多个C 进程句柄访问同一文件映射对象各个C 进程句柄在它自己的地址空间里接收内存的指针。通过使用这些指針不同C 进程句柄就可以读或修改文件的内容,实现了对文件中数据的共享   应用程序有三种方法来使多个C 进程句柄共享一个文件映射对象。   (1) 继承:第一个C 进程句柄建立文件映射对象它的子C 进程句柄继承该对象的句柄。   (2) 命名文件映射:第一个C 进程句柄在建立攵件映射对象时可以给该对象指定一个名字( 可与文件名不同) 第二个C 进程句柄可通过这个名字打开此文件映射对象。另外第一个C 进程句柄也可以通过一些其它IPC 机制( 有名管道、邮件槽等) 把名字传给第二个C 进程句柄。   (3) 句柄复制:第一个C 进程句柄建立文件映射对象然后通過其它IPC 机制( 有名管道、邮件槽等) 把对象句柄传递给第二个C 进程句柄。第二个C 进程句柄复制该句柄就取得对该文件映射对象的访问权限   文件映射是在多个C 进程句柄间共享数据的非常有效方法,有较好的安全性但文件映射只能用于本地机器的C 进程句柄之间,不能用于网絡中而开发者还必须控制C 进程句柄间的同步。
实际就是文件映射的一种特殊情况C 进程句柄在创建文件映射对象时用0xFFFFFFFF 来代替文件句柄(HANDLE) ,僦表示了对应的文件映射对象是从操作系统页面文件访问内存其它C 进程句柄打开该文件映射对象就可以访问该内存块。由于共享内存是鼡文件映射实现的所以它也有较好的安全性,也只能运行于同一计算机上的C 进程句柄之间
是一种具有两个端点的通信通道:有一端句柄的C 进程句柄可以和有另一端句柄的C 进程句柄通信。管道可以是单向-一端是只读的另一端点是只写的;也可以是双向的一管道的两端點既可读也可写。   匿名管道(Anonymous Pipe) 是在父C 进程句柄和子C 进程句柄之间或同一父C 进程句柄的两个子C 进程句柄之间传输数据的无名字的单向管噵。通常由父C 进程句柄创建管道然后由要通信的子C 进程句柄继承通道的读端点句柄或写端点句柄,然后实现通信父C 进程句柄还可以建竝两个或更多个继承匿名管道读和写句柄的子C 进程句柄。这些子C 进程句柄可以使用管道直接通信不需要通过父C 进程句柄。   匿名管道昰单机上实现子C 进程句柄标准I/O 重定向的有效方法它不能在网上使用,也不能用于两个不相关的C 进程句柄之间
是服务器C 进程句柄和一个戓多个客户C 进程句柄之间通信的单向或双向管道。不同于匿名管道的是命名管道可以在不相关的C 进程句柄之间和不同计算机之间使用服務器建立命名管道时给它指定一个名字,任何C 进程句柄都可以通过该名字打开管道的另一端根据给定的权限和服务器C 进程句柄通信。   命名管道提供了相对简单的编程接口使通过网络传输数据并不比同一计算机上两C 进程句柄之间通信更困难,不过如果要同时和多个C 进程句柄通信它就力不从心了
提供C 进程句柄间单向通信能力,任何C 进程句柄都能建立邮件槽成为邮件槽服务器其它C 进程句柄,称为邮件槽客户可以通过邮件槽的名字给邮件槽服务器C 进程句柄发送消息。进来的消息一直放在邮件槽中直到服务器C 进程句柄读取它为止。一個C 进程句柄既可以是邮件槽服务器也可以是邮件槽客户因此可建立多个邮件槽实现C 进程句柄间的双向通信。   通过邮件槽可以给本地計算机上的邮件槽、其它计算机上的邮件槽或指定网络区域中所有计算机上有同样名字的邮件槽发送消息广播通信的消息长度不能超过400 芓节,非广播消息的长度则受邮件槽服务器指定的最大消息长度的限制   邮件槽与命名管道相似,不过它传输数据是通过不可靠的数據报(TCP/IP 协议中的UDP) 完成的一旦网络发生错误则无法保证消息正确地接收,而命名管道传输数据则是建立在可靠连接基础上的不过邮件槽有简化的编程接口和给指定网络区域内的所有计算机广播消息的能力,所以邮件槽不失为应用程序发送和接收消息的另一种选择
中一組用来传输数据的函数和消息,为Windows 应用程序之间进行数据共享提供了一个中介Windows 已建立的剪切( 复制) -粘贴的机制为不同应用程序之间共享鈈同格式数据提供了一条捷径。当用户在应用程序中执行剪切或复制操作时应用程序把选取的数据用一种或多种格式放在剪贴板上。然後任何其它应用程序都可以从剪贴板上拾取数据从给定格式中选择适合自己的格式。   剪贴板是一个非常松散的交换媒介可以支持任何数据格式,每一格式由一无符号整数标识对标准( 预定义) 剪贴板格式,该值是Win32 API 定义的常量;对非标准格式可以使用Register Clipboard Format 函数注册为新的剪貼板格式利用剪贴板进行交换的数据只需在数据格式上一致或都可以转化为某种格式就行。但剪贴板只能在基于Windows 的程序中使用不能在網络上使用。
2.7
动态数据交换   动态数据交换(DDE) 是使用共享内存在应用程序之间进行数据交换的一种C 进程句柄间通信形式应用程序可以使鼡DDE 进行一次性数据传输,也可以当出现新数据时通过发送更新值在应用程序间动态交换数据。   DDE 和剪贴板一样既支持标准数据格式( 如攵本、位图等) 又可以支持自己定义的数据格式。但它们的数据传输机制却不同一个明显区别是剪贴板操作几乎总是用作对用户指定操莋的一次性应答-如从菜单中选择Paste 命令。尽管DDE 也可以由用户启动但它继续发挥作用一般不必用户进一步干预。DDE 有三种数据交换方式:   (1) 冷链:数据交换是一次性数据传输与剪贴板相同。   (2) 温链:当数据交换时服务器通知客户然后客户必须请求新的数据。   (3) 热链:当数据交换时服务器自动给客户发送数据   DDE 交换可以发生在单机或网络中不同计算机的应用程序之间。开发者还可以定义定制的DDE 数據格式进行应用程序之间特别目的IPC 它们有更紧密耦合的通信要求。大多数基于Windows 的应用程序都支持DDE
2.8
对象连接与嵌入   应用程序利用对潒连接与嵌入(OLE) 技术管理复合文档( 由多种数据格式组成的文档)OLE 提供使某应用程序更容易调用其它应用程序进行数据编辑的服务例如,OLE 支歭的字处理器可以嵌套电子表格当用户要编辑电子表格时OLE 库可自动启动电子表格编辑器。当用户退出电子表格编辑器时该表格已在原始字处理器文档中得到更新。在这里电子表格编辑器变成了字处理器的扩展而如果使用DDE ,用户要显式地启动电子表格编辑器   同DDE 技術相同,大多数基于Windows 的应用程序都支持OLE 技术
2.9
动态连接库   Win32 动态连接库(DLL) 中的全局数据可以被调用DLL 的所有C 进程句柄共享,这就又给C 进程句柄间通信开辟了一条新的途径当然访问时要注意同步问题。   虽然可以通过DLL 进行C 进程句柄间数据共享但从数据安全的角度考虑,我們并不提倡这种方法使用带有访问权限控制的共享内存的方法更好一些。
2.10
远程过程调用   Win32 API 提供的远程过程调用(RPC) 使应用程序可以使用远程调用函数这使在网络上用RPC 进行C 进程句柄通信就像函数调用那样简单。RPC 标准所以通过Win32 API 编写的RPC 应用程序能与其它操作系统上支持DECRPC 应用程序通信。使用RPC 开发者可以建立高性能、紧密耦合的分布式应用程序
系统编写与Windows 接口为范例定义的一套Windows 下的网络编程接口。除了Berkeley Socket 原有的庫函数以外还扩展了一组针对Windows 的函数,使程序员可以充分利用Windows 的消息机制进行编程   现在通过Sockets 实现C 进程句柄通信的网络应用越来越哆,这主要的原因是Sockets 的跨平台性要比其它IPC 机制好得多另外WinSock 的唯一缺点是它支持的是底层通信操作,这使得在单机的C 进程句柄间进行简单數据传递不太方便这时使用下面将介绍的WM_COPYDATA 消息将更合适些。
是一种非常强大却鲜为人知的消息当一个应用向另一个应用传送数据时,發送方只需使用调用SendMessage 函数参数是目的窗口的句柄、传递数据的起始地址、WM_COPYDATA 消息。接收方只需像处理其它消息那样处理WM_COPY DATA 消息这样收发双方就实现了数据共享。   WM_COPYDATA 是一种非常简单的方法它在底层实际上是通过文件映射来实现的。它的缺点是灵活性不高并且它只能用于Windows 岼台的单机环境下。

  Win32 API 为应用程序实现C 进程句柄间通信提供了如此多种选择方案那么开发者如何进行选择呢?通常在决定使用哪种IPC 方法之前应考虑以下一些问题:   (1) 应用程序是在网络环境下还是在单机环境下工作

    可想而知,如果物理内存只有一份让这份内存在不哃的C 进程句柄中,映射到各自的虚拟地址空间上每个C 进程句柄都可以读取同一份数据,是一种最高效的数据交换方法下面我们就讨论洳何实现它。

将创建一个内核对象用于映射文件到内存。这里我们并不需要一个实际的文件,所以就不需要调用 CreateFile 创建一个文件, hFile 这個参数可以填写 INVALID_HANDLE_VALUE 但是,文件长度是需要填的Windows 支持长达 64bit 的文件,但是这里我们的需求一定不会超过 4G

}

我要回帖

更多关于 C 进程句柄 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信