王辉老师答网友1(转)

问:打开关闭,读写等操作,有这方面的文档吗?

答:sys_open(),sys_read()sys_write();

问:ULK页面回收那章说anonymous memory region是堆和栈区,而在讲进程地址空间layout时把anonymous memory region放在堆区和栈区之间

答:是指已经被分配但尚未被使用的内存区域;

问:请问各位大虾,写linux下的驱动时主要读datasheet的哪个部分?是不是对每个部分都要看呢(比如说II2S总线,我们在看它的datasheet时是不是要理解它的总线协议等所有详细知识呢?还是只要仅仅看某些和控制(XXCON)、模式(XXMOD)数据传输、数据接受等寄存器呢?)。都说写驱动要熟悉硬件知识,是不是仅仅知道这些寄存器就好了呢?还是说简单的再了解下其它的有关知识?请各位大虾不吝赐教!

答:最起码你要从datasheet中读懂这个设备的工作原理以及数据传输方式和格式,甚至是时序问题,如果你想做一个好的驱动程序员,想写一个你自己和别人都放心的驱动程序,那么你必须了解设备的硬件原理,然后看设备相关寄存器的为定义就OK了;了解硬件原理和操作方法(寄存器)写驱动程序是写驱动程序的基础,了解了设备原理就可以写出各种形式的驱动程序,Linux驱动程序只是其中的一种形式而已;

问:我让一个进程获得了自旋锁,然后执行schedule_timeout休眠10s(只是测试),之后再释放自旋锁;接着另外一个进程又想获得这个自旋锁,接着就死机了.如果内核是随处都可以抢占的话,是不应该死机的.
请教高手,不是说2.6的内核已经可以抢占了,是不是我用的内核版本编译的不对?

答:2.6内核肯定是可以抢占的,当然需要在编译前配置内核时使能抢占;但是自旋锁只能用于多核处理器,对于单处理器来说是不起作用的;因为自旋锁的自旋是始终占用CPU的,如果在单处理器上自旋,系统就死了。

问:linux-2.6.14.1中的/include/asm/arch-s3c2410/regs-iic.h中定义了 IIC的寄存器的地址:
#define S3C2410_IICREG(x) (x)
#define S3C2410_IICCON    S3C2410_IICREG(0x00)
#define S3C2410_IICSTAT   S3C2410_IICREG(0x04)
#define S3C2410_IICADD    S3C2410_IICREG(0x0
#define S3C2410_IICDS     S3C2410_IICREG(0x0C)
#define S3C2440_IICLC   S3C2410_IICREG(0x10)

我将/linux-2.6.14.1/include/asm/arch-s3c2410/map.h文件下的如下:

/* IIC hardware controller */
#define S3C24XX_VA_IIC    S3C2410_ADDR(0x00C00000)
#define S3C2400_PA_IIC    (0x15400000)
#define S3C2410_PA_IIC    (0x54000000)
#define S3C24XX_SZ_IIC    SZ_1M
#define VA_IIC_BASE    (S3C24XX_VA_IIC)

VA_IIC_BASE加入到  #define S3C2410_IICREG(x)   (x)  变成 #define S3C2410_IICREG(x)        (VA_IIC_BASE+X)

这样在驱动中直接利用readb()writeb()函数对S3C2410_IICCON   S3C2410_IICSTAT  
S3C2410_IICADD
S3C2410_IICDS   直接访问,编译通过后,在板子运行出错。

不知道这么加是不是IIC的寄存器在系统系统里映射地址。
看了别的寄存器的定义好象都行。
盼指点下,谢谢

答:不应该修改,因为你修改之后原来引用这些宏的函数就无法运行了,比如你改了之后driver/i2c/busses/i2c-s3c2410.c中的s3c24xx_i2c_init()函数就无法运行了,系统会出错;

问:我在用S3C2410IIC,可是老是写不出去,读不出来,后来跟踪发现,IICCON这个寄存器的第五位中断挂起标志,从来不变为1 ,表示没有完成发送和接受。不知道IICCON不起作用了。
        
我是在LINUX-2.6下写的驱动。各个寄存器的培植都好象没有问题。
不知道为什么?给点指点

答:1)首先用示波器看一下IIC的时钟线是否有时钟,再查一下数据线上是否有你想要的数据波形;
2
)仔细阅读s3c2410芯片的datasheetiic部分;
3
)对照datasheet中的寄存器说明查看你的系统中的IIC寄存器状态,分析问题;

问:本人想学嵌入式linux,现在不知道改买什么样的书,大家给我推荐一两本吧!

答:《嵌入式系统Linux内核开发实战指南(ARM平台)》最合适;

问:编了内核搭建了一下驱动开发的环境,也参考网上的驱动例子写了几个很白痴的模块(没做具体的什么事,只是打印点消息,传个参数看看之类的),全当用来了解下写模块的大概流程罢了,还算顺利
但是现在比较迷茫了,不知道下一步该做什么了呢?
请各位指点下,谢谢!

答:找一块你能看到原理图的板子,试着写一个简单的串口驱动试一下

问:本来是做PCI-E,但其中对于BAR没讲,应该是兼容的所以又看了一下PCI的规范,里面倒是专门讲了,但还是不明白:

1. BAR0~BAR1
只是MemoryI/O空间的大小及相关的特性。在Linux中有如下定义:

#define pci_resource_start(dev,bar)   ((dev)->resource[(bar)].start)
#define pci_resource_end(dev,bar)     ((dev)->resource[(bar)].end)
#define pci_resource_flags(dev,bar)   ((dev)->resource[(bar)].flags)


但这些值系统是怎么得到的?

2.
我看过一个实际的PCI-E的驱动,它里面是用ioremapBAR0映射到虚拟地址使用的。但实际的物理内存在哪,板子上?看了许多资料都不明白,规范中也没讲。

如果只是做驱动知道这些信息可能也够了,但现在我们的问题是板子也是自己做的,所以需要更深入的了解;而那个我能拿到驱动的板子没有他们的硬件开发手册,所以并不知道板子里面具体是如何设计的。

答:第一个问题:这些值是在Linux系统初始化过程中设置的,由biosbootloader)设置bar,然后Linux启动时会从bar中读取起始地址和大小以及空间类型,并且如果需要会进行适当修改,内核也可以重新设置这些参数,但通常不必要;
第二个问题:实际物理空间在PCI卡上,可能是PCI卡上的内存,也可能是PCI卡上的寄存器空间或其他IO空间,反正是在PCI卡上,但它已经被映射到了整个系统的统一的地址空间,这就是BAR中的值,但BAR中的值是物理地址,所以必须用iqremap将其映射到虚拟地址空间才能被内核使用;
第三个问题,如果你只是想写驱动,不需要别的,只需要了解PCI总线的工作原理就可以,你只需首先将0xffffffff写入bar,然后读出来,就知道这个空间的类型和大小了,然后把你想把它映射到系统中的什么地址(是物理地址)就把这个物理地址写入bar就可以了;如果要访问这个地址空间必须如上所述用ioremap将这个地址空间映射到虚拟内存空间;注意,bar中的都是总线地址,总线地址都是物理地址;而Linux内核使用的都是虚拟地址,当然如果CPU中没有MMU单元那么内核也只是使用物理地址,如s3c44b0s3c4510等;

问:在内核态怎样申请连续的256M内存,alloc_pages最大也就8M,试过ioremap,但其它模块拿这个地址会有问题。有没有其它方法?谢谢!

答:在系统启动完之前(也就是mem_init()函数执行之前)用类似alloc_bootmem()的函数来申请就可以,这样申请的内存空间系统启动之后不会被Linux内核管理,也就是不会被内核回收,内核不知道有这段内存,你可以自己放心使用;
系统启动后(确切地说是mem_init()函数执行之后)一次能申请到的最大内存空间是由头文件include/linux/kmalloc_sizes.h中的内容来限定的,当然也可以通过修改这个文件来增加,但这样不安全,如果系统中申请大块内存的程序太多,系统效率会大大降低,也很容易死掉.

为什么还在争这个问题,前面不是说了吗,在start_kernel()函数中的mem_init()执行之前用类似alloc_bootmem()的函数申请就可以了,这样申请到的内存地址返回的是内核逻辑地址,只要系统启动了MMU功能那么系统就看不到物理地址的;这个内核逻辑地址就是0XC0000000~HIGH_MEM之间的与物理内存地址一一对应的虚拟地址,你是可以访问的,但由于你在mem_init()执行之前没有释放这部分内存,所以内核不会回收这部分内存,也就是内核不可能将这部分内存纳入伙伴系统而分配给其他程序,也就只有知道这部分内存的人才能使用它;

问:linux内核源代码情景分析的第二章看到这句话
系统空间占据了虚拟空间中的高1GB字节,在物理的内存中却总是从最低的地址(0)开始的。
所以,对于内核来说,其地址的映射是很简单的线性映射,0xc0000000就是两者之间的位移量。
也就是说,对于系统空间而言,给定一个虚地址x,其物理地址是从x中减去0xc0000000
相应地,给定一个物理地址x,其虚地址是x+0xc0000000

不知道怎么理解?
难道说系统空间的线性地址不经过页表就直接线性映射到物理地址上吗?
而进程空间的线性地址得经过页表的转换才能映射到物理地址上的
这两者是不一样的?

答:都是要通过页表才能实现映射的;
在物理的内存中却总是从最低的地址(0)开始的这句话是不对的,是要针对具体处理器平台的,虽然大部分处理器平台的物理内存地址是可以被配置成从0开始的,但不是所有的都是,所以这句话是不确切的,当然我没看过这本书,也许这句话在上下文中是特指某个平台。

问:最近在看到中断的一个概念
可延迟函数
中断中的可延迟函数 是不是 就是在开中断的情况下可被中断的嵌套执行的函数?
请高手指点一下

答:这里并不必然涉及到嵌套;
可延迟函数的功能之一就是让中断处理程序中不重要的部分留到本次中断之后去处理,以免系统长时间处于中断处理状态,影响系统性能和响应速度。
中断的上半部分在中断上下文中运行,下半部分在专门的延迟处理监护进程中运行,不是中断上下文中运行。

中断处理器的后半部分既可能在中断上下文中运行,也可能在进程上下文中运行,当退出中断时 会去检查是否有停靠的后半部分需要处理,如果是,那么处理它(们),这时的后半部分自然是运行在中断上下文中,而如果后半部分反复被重新激活并且超过一定的限制次数,那么,系统会唤醒软中断看护进程ksoftirqd,自己则退出中断,这样余下的后半部分则将被系统的ksoftirqd进程来处理,这时后半部分当然是运行在进程上下文中的;

问:>>中断的上半部分在中断上下文中运行,下半部分在专门的延迟处理监护进程中运行,不是中断上下文中运行。

小弟以为下半部也是运行于中断上下文的.
LKD
中讲到:

QUOTE:

When executing an interrupt handler or bottom half, the kernel is in interrupt context. Recall that process context is the mode of operation the kernel is in while it is executing on behalf of a processfor example, executing a system call or running a kernel thread. In process context, the current macro points to the associated task.
因为运行于下半部的时候, 仍然不是作为某个进程去运行的, 虽然此时使用了某个进程的内核栈.

答:我们不要用某本书的某句话来应证技术问题,对于Linux一定要用实际的内核代码来说话,不要迷信书本,任何结论都要建立在理解内核代码的基础之上,lkd3ldd3上都有值得商榷的地方,比如lkd3上说在系统启动阶段可以申请高端内存,但我从内核源代码中却没有读出这种可能,所以我觉得这种说法是错误的!

问:你说的申请高端内存是指逻辑地址3G+896M以上的那部分?

答:对于x86系统可以认为高端内存就是3G+896M以上的部分,896x86系统中的一个经验值,剩下的128MB线性空间是留给vmalloc()kmap()kmap_atomic()等函数的,但这个经验值是可以改的,比如:如果系统中事实上只有128MB物理内存,那么把高端内存的值定到896事实上没有意义,而且浪费了很多线性地址空间;
事实上,在嵌入式系统中,高端内存的开始地址为0xC0000000+系统实际物理内存大小,仔细阅读源代码就能看出这些原理的,不要拘泥于纯理论的某些概念,要活学活用!

问:本人是linux的菜鸟,刚刚接触嵌入式这一块,导师分配了毕设题目《嵌入式平台IDE接口驱动与文件系统设计》,硬件平台是优龙的f3c2410试验箱,不知道从何下手,希望达人们给点建议。关键是不知道这个项目的整体框架是什么,需要哪些具体的知识准备,先谢过了!

答:你的导师出的题还是比较大的,IDE接口驱动是设备驱动或设备管理组件,而文件系统则是操作系统中的另一核心组件,文件系统必须通过设备驱动程序(如IDESCSISATA接口驱动程序)才能访问到硬盘的,也就是说文件系统是基于块设备驱动程序之上的;
我建议你:看懂s3c2410实验箱的原理图,特别是IDE接口部分,再阅读s3c2410的数据手册,再阅读IDE接口标准,熟悉IDE硬盘命令,再了解Linux中块设备驱动程序的编写方法,了解Linux文件系统的原理和编写方法;
问:我现在的工作做的是ARM+LINUX 的产品开发,底层工作较多,也有一些应用.
现在有一个工作,INTEL 做芯片软件测试开发工作的,估计也就是测试没有开发的工作, 用的是X86/LINUX 平台, 因为对这个行业不熟, 所以请教这份工作对我的现在的嵌入式工作有发展么??
请大家给一个中肯的建议,谢谢

答:首先嵌入式正是与x86相对的,当然我并不反对你去多熟悉一种处理器平台,但x86在嵌入式系统领域应用是极少的,而且我个人觉得不应该把x86引到嵌入式系统中来,包括pc104,否则intel会窃笑的!
其次做开发肯定比做测试更能锻炼一个人的技术研发能力,虽然高级测试也需要很多技术,但侧重点不一样,测试是挖空心思使用各种工具各种手段来挑产品的毛病,它的技术不一定是嵌入式本身,而开发才是学习锻炼嵌入式Linux开发能力、掌握嵌入式Linux原理的最好方式,所以如果你还想在嵌入式Linux技术开发道路上发展下去,那么我建议你不要那份intel的测试工作,工资再高也不要去,可以多做一些其他的嵌入式平台,比如中国的龙芯(MIPS)等。

你可能感兴趣的:(c,linux,工作,嵌入式,平台,linux内核)