不知道大家是否看到几万行的代码是什么心情。 有人说过,阅读别人的代码是一种享受。下午的时候,泡上一壶好茶,坐在自己家的阳台上,阅读代码。嗯嗯,比看小说要有意思的多了。学习别人的思想,让自己的思维更敏捷。
其实主要是做笔记,一个大的项目,或程序,估计几万行代码是下不来的。 就像谁也不能把金庸全集一口气看完一样。那么知道自己看到哪了,上下文如何衔接起来,就要靠记录了。你可以选择有笔纸,选择键盘敲,无所谓。
你可以选择用图,或用自己的大白话。自己习惯,和要适合自己大脑的思维方式来定。
我比较喜欢用图的,有助于逻辑思维的记忆和锻炼。
图大概有:
--流程图;
--时序图;
--数据流图;
对于一个大的项目,一个也不能少。
前一段时间分析linux内核中的usb gadgetfs 驱动,相关文件有$(kernel)/device/usb/gadget/ inode.c和一个
USB官网上的用户态驱动usb.c。
下面是我的记录用的是“树形结构”(自己起的名字,呵呵),不是很全,仅提供思路,希望大家可以在代码中找到乐趣,思维更加灵敏。
这个是USB.C的:
int main (int argc, char **argv) | |/* random initial serial number */ | | 接收控制参数; | | 改变路径到/dev/gadget; | |-- init_device (); /* 设备初始化 */ | | | |-- autoconfig (); /* 自动配置端点 */ | | | | | | 取得设备名称,信息; | | | | | | 设置端点地址,和端点名; | | |-[R] | | | |-- open (DEVNAME, O_RDWR); /* 打开设备文件 */ | | | | /* write full then high speed configs */ | |-- static char *build_config (char *cp, const struct usb_endpoint_descriptor **ep); | | | | | | 一个cp指针指向buf, 用buf来存储个描述符; | | |buf | | | ________ | | | | | | | | | config | | | | | | | | | |interface | | | | | | | | | | ep | | | | |________ | | | | | | |-[R] | | | | /* and device descriptor at the end */ | | | |-- write (fd, &buf [0], cp - &buf [0]); /* write dev descriptor */ | | | |--[return] 一个配置符齐全的fd; | | | /* control thread, handles main event loop */ |-- ep0_thread (&fd); /* 将init_device 后的fd 传给了它 */ | | | |当有事件以信号的方式传递给它时, | |它是用wait等待的sigwait (&sigs, &tmp); | | | |然后利用switch(tmp)来处理不同类型的事件,然后做相应的控制 | | | |/* loop */ | | case GADGETFS_SETUP: | | handle_control (fd, &event [i].u.setup); | | | | static void handle_control (int fd, struct usb_ctrlrequest *setup) | | | | | | | |- struct usb_ctrlrequest | /*this structure is used to send control requests to a USB device.*/ | | 处理标准的USB设备请求命令 | |switch(setup->bRequest) | | | | | |case USB_REQ_SET_CONFIGURATION: | | if (setup->bRequestType != USB_DIR_OUT) | | goto stall; | | if (verbose) | | fprintf (stderr, "CONFIG #%d/n", setup->wValue); | | | | ... | | switch (setup->wValue) { | | case CONFIG_VALUE: | | start_io (); /* 启动线程 */ | | break; | | case 0: | | stop_io (); | | break;
static void start_io () | |除ep0外,其他2个端点是以线程的方式运行的,在这里启动2线程 | |/*create source thread*/ /In/ | |/*create sink thread*/ /Out/ /* source endpoint thread */ static void *simple_source_thread (void *param) | | 配置端点 source_open /* 一个可以配置端点的宏,在下面有它的实现 */ | |--while(status > 0) { len = fill_in_buf (buf, sizeof buf); if (len > 0) status = write (source_fd, buf, len); } | | /* sink endpoint thread */ static void *simple_sink_thread (void *param) | |配置端点 sink_open /* 一个可以配置端点的宏,在下面有它的实现 */ | |--while{ status = read (sink_fd, buf, sizeof buf);
if (status < 0) break; status = empty_out_buf (buf, status); } | | | #define source_open(name) / ep_config(name,__FUNCTION__, &fs_source_desc, &hs_source_desc) #define sink_open(name) / ep_config(name,__FUNCTION__, &fs_sink_desc, &hs_sink_desc) /* you should be able to open and configure endpoints * whether or not the host is connected */ static int ep_config (char *name, char *label, struct usb_endpoint_descriptor *fs, struct usb_endpoint_descriptor *hs) | | |
这个是linux内核中的inode.c(gadgetfs的实现),不是很全,现在正在看。
/* * read kernel/driver/usb/gadget/inode.c * * gadgetfs gadget api * * date : 1-6-2007 * */ [mynote]: 1.gadgetfs 2.dev_config 3.dev operation 4.ep_config 5.ep_peration | |-- register_filesystem (&gadgetfs_type) | | /* when __init module_init */ | /* gadgetfs_type object have a implant structure.*/ |-- struct file_system_type gadgetfs_type | |-- gadgetfs_get_sb | | /* when "mount -t gadgetfs path /dev/gadget" ends up here | will call gadgetfs_get_sb | */ |--gadgetfs_get_sb | | | |//call a system call , register gadgetfs_fill_super to kernel. | |--get_sb_single (t, flags, opts, gadgetfs_fill_super) | | /* a main function, kernel will callback this function of inode.c */ | 仅仅用于探测一个UDC的设备名字,然后在/DEV/GADGET/下建立如下文件节点 | 1.$CHIP | 2.$ep0 | 3.$other ep |-- gadgetfs_fill_super | | |1. |/* fake probe to determine $CHIP */ |--(void) usb_gadget_register_driver (&probe_driver); | | sturct usb_gadget_driver probe_driver | | --gadgetfs_probe | | | 1.[input] usb_gadget device | | | 2.CHIP = gadget->name /* 将设备名称给CHIP */ | | |/*[??note]when*/ dev_config | | | |/* triggers gadgetfs_bind(); then we can enumerate. */ | |--value = usb_gadget_register_driver (&gadgetfs_driver) | | |2. | /*建立跟节点root inode*/ | gadgetfs_make_inode | |3. 建立ep0节点文件 | /* the ep0 file is named after the controller we expect; | user mode code can use it for sanity checks, like we do. | */ | | |4. 建立其他节点文件 |/* other endpoint files are available after hardware setup, | from binding to a controller. |*/ | |