u盘 只读 嵌入式linux,读Linux那些事儿之我是U盘笔记(五)

1、在Linux内核中,整个scsi 子系统被分为三层.upper level,mid level,lower level;

解释:来说说这三层吧:

upper level,用伟大的汉语来讲,就是最上层,她是和操作系统打交道的,比如您要是有一块scsi 硬盘,那么您就需要使用sd_mod.o这么一个模块,她实际上是与硬件无关的,是纯粹的软件上的抽象出来的数据结构组建的模块.

mid level,中层,实际上这层才是真正的核心层,江湖上人称scsi-core,即scsi核心层,她提供了支持scsi的核心数据结构和函数,这一层对应的模块是scsi_mod.o,系统中要想使用scsi 设备,首先必须加载她,反过来,只有所有的scsi 设备的模块都被卸载了才能够卸载她.陆游就曾如此形容scsi 核心层,无意苦争春,一任群芳妒.

lower level,底层.很不幸,如果您要写驱动,八成就是写的底层,正如现实中的我们一样,生活在社会的最底层.因为upper level 和mid level都已经基本上确定了,她们和硬件没关系.能留给您做的事情只能是底层.现实就是这样,尤其对80后的来说,生存的压力让80后不可能再如70后那样,能做的只有面对现实.

2、__attribute__:这是gcc的关键字,是,描述函数,变量,类型的属性

通常__attribute__(单词attribute前后各两个 underscore,即下划线.)出现在定义一个变量/函数/类型的时候,她紧跟在变量/函数/类型定义的后面;

Eg:unsigned long hostdata[0]__attribute__ ((aligned (sizeof(unsigned long))));

aligned属性和packed属性.这两个都是和字节对齐有关的属性,aligned 是按照定义的自己对齐,packed是紧凑型,表示节省空间

3、现在要模拟scsi:需要用到scsi三个函数

三个函数分别是:scsi_host_alloc(),scsi_add_host(),scsi_scan_host();

scsi_host_alloc()中就会给咱们申请内存空间;

scsi_add_host()scsi核心层才知道有这么一个host的存在

scsi_scan_host()函数被调用了之后,真正的设备才被发现

scsi核心层是认struct Scsi_Host这个结构体的,而这个结构体在设计的时候就专门准备了一个unsigned long hostdata[0]来给别的设备驱动使用.

4、kernel_thread()解释:

就会有两个进程,一个是父进程,一个是子进程,子进程将会执usb_stor_control_thread(),而us是作为usb_stor_control_thread函数的参数(实参),CLONE_VM标志表征父子进程之间共享地址空间,执行完usb_stor_control_thread()之后,子进程就结束了,她会调用exit()函数退出.而父进程继续顺着usb_stor_acquire_resources()函数往下走,kernel_thread()函数对于父进程而言返回的是子进程的进程id,所以802行先判断,若是返回值p 小于0,则说明出错了,否则,那就把p赋给us 的元素pid;

5、wait_event_interruptible_timeout():

解释:这个函数其实是一个宏,

#define wait_event_interruptible_timeout(wq, condition, timeout)\

({\

long __ret = timeout;\

if (!(condition))\

__wait_event_interruptible_timeout(wq, condition, __ret); \

__ret;\

})

它代表着Linux中的一种等待机制,等待某个事件的发生;

第一个参数是一个等待队列头,即wait_queue_head_t定义的变量,在LK 2.6中使用init_waitqueue_head()函数初始化这个等待队列

第三个参数是设置超时,比如咱们这里设了5s,这表示如果5秒到了,那么函数会返回0,不管其它条件如何

第二个参数是一种等待的条件,或者说等待的事件,如果条件满足了,那么函数也会返回,条件要是不满足,那么这个进程会进入睡眠,不过interruptible表明了信号可以把她中断.一旦进入睡眠,那么有三种情况,一种是wake_up或者wake_up_interruptible函数被另一个进程执行,从而唤醒她,第二种是信号中断她,第三种就是刚才讲的超时,时间到了,自然就会返回;

在内核2.6.18 montavista linux中有一个

unsigned long fastcall __sched wait_for_completion_interruptible_timeout(struct completion *x,

unsigned long timeout)函数,在schd.c中是个函数,同理

6、内核休眠另一方法,电源管理方面

对于usb 设备,它可以进入suspend状态,如果flgs设置了PF_FREEZE这个标记,内核将调用refrigerator();函数让该进程休眠

7、U盘能够工作所需要的模块:usbcore,scsi_mod,sd_mod,usb-storage

其中:sd_mod是scsi disk的驱动程序

8、struct scsi_cmnd *srb很重要的结构,是scsi用来发命令的结构,如usb 使用的urb

U盘驱动这里使用,是为了唤醒usb_stor_control_thread 线程,这个线程开始的时候:

if(down_interruptible(&us->sema))    //等待scsi queuecommand来唤醒

break;

该线程休眠了,现在除了usb退出,就修要别人去唤醒这个线程,当然使用配套的

up(&(us->sema));了,这个函数定义在queuecommand里面;这个命令是scsi发送的,这个函数定义在usb_stor_host_template里边;

9、确定一个scsi设备的三个元素:unsigned int id, lun, channel

关系:一个scsi 卡所控制的设备被划分为几层,先是若干个channel,然后每个channel 上有若干个target,每个target用一个target id来表征,然后一个target可以有若干个lun,而咱们这里判断的是target id.对于不支持多个target的设备,她必须为0.对于绝大多数usb mass storage设备来说,它们的target id肯定为0,

但是世界上总是有那么多怪事,有些设备厂家就是要标新立异,它就是要让你个设备支持多个target,于是它就可以设置US_FL_SCM_MULT_TARG这么一个flag

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值