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表明 |