Linux复习(六)

一、内核

操作系统是一系列程序的集合,其中最重要的部分构成了内核

单内核/微内核
   单内核是一个很大的进程,内部可以分为若干模块,运行时是一个独立的二进制文件,模块间通讯通过直接调用函数实现
   微内核中大部分内核作为独立的进程在特权下运行,通过消息传递进行通讯
Linux内核的能力
    内存管理,文件系统,进程管理,多线程支持,抢占式,多处理支持
Linux内核区别于其他UNIX商业内核的优点
   单内核,模块支持
   免费/开源
   支持多种CPU,硬件支持能力非常强大
   Linux开发者都是非常出色的程序员
   通过学习Linux内核的源码可以了解现代操作系统的实现原理


层次结构



二、模块&驱动


许多常见驱动的源代码集成在内核源码里
也有第三方开发的驱动,可以单独编译成  模块.ko
驱动的编译需要内核头文件的支持 #include <linux/kernel.h>            

1.加载模块的命令:
1)底层命令
   insmod
   rmmod
2)高层命令
   modprobe
   modprobe -r

2.

内核编程和外围程序的差别。(主观题,要能写出一段)   重点!



3.

内核编程的注意点


不能使用C库来开发驱动程序
没有内存保护机制
小内核栈
 并发上的考虑



4.

内核模块的一个简单例子(要能看懂)



#include <linux/kernel.h>            
#include <linux/module.h>
#include <linux/init.h>

static int __init hello_init(void)
{
printk(KERN_INFO "Hello world\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye world\n");
}
module_init(hello_init);
module_exit(hello_exit);

• static int __init hello_init(void)
• static void __exit hello_exit(void)
– Static声明,因为这种函数在特定文件之外没有其它意义
– __init标记, 该函数只在初始化期间使用。模块装载后,将
该函数占用的内存空间释放
– __exit标记 该代码仅用于模块卸载。
• Init/exit
– 宏:module_init/module_exit
– 声明模块初始化及清除函数所在的位置
– 装载和卸载模块时,内核可以自动找到相应的函数
module_init(hello_init);
module_exit(hello_exit);



5.

驱动的代码要求能看懂


PDF ch3-2 P25

6.

模块参数的传递





7. /proc和/dev

1)/proc


在linux的根目录下有一个/proc目录,/proc文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在Linux内核空间和用户空间之间进行通信。在/proc文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的(即在我们执行指令的那一刹那才产生的)

/proc文件系统包含了:

1. 1. 一些目录(用作组织信息的方式)
2. 例如linux对于当前运行中的每一个进程都在/proc目录下建立一个目录(目录名就是process-id),例如init的进程号是1,则目录名也是1
3. 2. 虚拟文件
4. 虚拟文件可以向用户呈现内核中的一些信息,也可以用作一种从用户空间向内核发送信息的手段


2)/dev

设备文件分为两种: 块设备文件(b)和字符设备文件(c),对于/dev我们需要明白,它不是设备驱动,linux有自己的设备驱动,/dev下的文件只是访问相应驱动的接口
设备文件一般存放在/dev目录下,对常见设备文件作如下说明:

01. /dev/hd[a-t]:IDE设备
02. /dev/sd[a-z]:SCSI设备
03. /dev/fd[0-7]:标准软驱
04. /dev/md[0-31]:软raid设备
05. /dev/loop[0-7]:本地回环设备
06. /dev/ram[0-15]:内存
07. /dev/null:无限数据接收设备,相当于黑洞
08. /dev/zero:无限零资源
09. /dev/tty[0-63]:虚拟终端
10. /dev/ttyS[0-3]:串口
11. /dev/lp[0-3]:并口
12. /dev/console:控制台
13. /dev/fb[0-31]:framebuffer
14. /dev/cdrom => /dev/hdc
15. /dev/modem => /dev/ttyS[0-9]
16. /dev/pilot => /dev/ttyS[0-9]
17. /dev/random:随机数设备
18. /dev/urandom:随机数设备

8.驱动的类型
Linux系统将设备分为3种类型:字符设备、块设备和网络接口设备。
• 字符设备 Character Driver 
• 块设备 Block Driver
• 网络接口设备 Network Driver

字符设备character device:采用字符流方式访问的设备,如字符终端,串口,一般顺序访问,但也可以前后移动访问指针,如帧捕捉卡。
常见要开发的有:触摸屏,自定义键盘,视频捕捉设备,音频设备等
块设备Block device:采用数据块方式访问的设备,如磁盘等,可以随意移动访问。和字符设备的差异在于内核内部管理数据的方式,如采用缓存机制等。并必须支持 mount文件系统。基本上不用自己开发,象硬盘,光盘,USB存储设备等Linux都提供了
网络接口 network interface(需要自己开发):数据包传输方式访问的设备,和上两者不同。通过ifconfig来创建和配置设备。网络驱动同块驱动最大的不同在于网络驱动异步接受外界数据,而块驱动只对内核的请求作出响应

其他:总线类,如USB, PCI, SCSI等,一般同其他驱动联合使用
常见要开发的如采用IIC,SPI,USB通信的一些设备驱动。


9.申请和释放设备的5个步骤及函数名

一个字符设备或者块设备都有一个主设备号和次设备号。
• 主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。
• 次设备号用来表示使用该驱动程序的各设备。

字符设备驱动程序的初始化加载过程:
• 申请设备号
• 定义文件操作结构体 file_operations
• 创建并初始化定义结构体 cdev
• 将cdev注册到系统,并和对应的设备号绑定
• 在/dev文件系统中用mknod创建设备文件,并将该文件绑定到设备号上

1)申请

2)file_operations

struct file_operations {
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
    ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
    int (*readdir) (struct file *, void *, filldir_t);
    unsigned int (*poll) (struct file *, struct poll_table_struct *);
    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *, fl_owner_t id);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, struct dentry *, int datasync);
    int (*aio_fsync) (struct kiocb *, int datasync);
    int (*fasync) (int, struct file *, int);
     ...  
};


struct file {
    /*
     * fu_list becomes invalid after file_free is called and queued via
     * fu_rcuhead for RCU freeing
     */
    union {
        struct list_head    fu_list;
        struct rcu_head     fu_rcuhead;
    } f_u;
    struct path        f_path;
#define f_dentry    f_path.dentry
#define f_vfsmnt    f_path.mnt
    const struct file_operations    *f_op;
    atomic_t        f_count;
    unsigned int         f_flags;
    mode_t            f_mode;
    loff_t            f_pos;
    struct fown_struct    f_owner;
    unsigned int        f_uid, f_gid;
    struct file_ra_state    f_ra;

    unsigned long        f_version;
#ifdef CONFIG_SECURITY
    void            *f_security;
#endif
    /* needed for tty driver, and maybe others */
    void            *private_data;

#ifdef CONFIG_EPOLL
    /* Used by fs/eventpoll.c to link all the hooks to this file */
    struct list_head    f_ep_links;
    spinlock_t        f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
    struct address_space    *f_mapping;
};





3)cdev的定义和初始化

4)注册

5)创建设备文件,并将该文件绑定到设备号上

4.

内核模块的一个简单例子(要能看懂)

4.

内核模块的一个简单例子(要能看懂)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>