现在的位置: 首页 > 综合 > 正文

linux 0.11 内核学习 — char_dev.c

2013年01月16日 ⁄ 综合 ⁄ 共 2542字 ⁄ 字号 评论关闭

/*

 *  linux/fs/char_dev.c

 *

 *  (C) 1991  Linus Torvalds

 */

 

#include <errno.h>

#include <sys/types.h> // 定义了基本的系统数据类型

 

#include <linux/sched.h>

#include <linux/kernel.h> // 含有一些内核常用函数的原形定义

 

#include <asm/segment.h>

#include <asm/io.h>

 

/* 中断读 */

extern int tty_read(unsigned minor,char * buf,int count);

/* 中断写 */

extern int tty_write(unsigned minor,char * buf,int count);

/* 定义字符设备读写函数指针类型 */

typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos);

 

/* 串口终端读写操作函数。参数 : rw读写命令,minor中断子设备号,buf缓冲区 */

/* count读写的字节数,pos读写操作当前指针,返回实际读写的字节数  */

static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos)

{

return ((rw==READ)?tty_read(minor,buf,count):

tty_write(minor,buf,count));

}

 

/* 终端读写操作函数,只是增加了对进程是否有控制终端的检测 */

static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos)

{

// 若进程没有对应的控制终端,则返回出错号

if (current->tty<0)

return -EPERM;

return rw_ttyx(rw,current->tty,buf,count,pos);

}

 

/* 内存数据读写函数,还没实现 */

static int rw_ram(int rw,char * buf, int count, off_t *pos)

{

return -EIO;

}

 

/* 内存数据读写操作函数。未实现 */

static int rw_mem(int rw,char * buf, int count, off_t * pos)

{

return -EIO;

}

 

/* 内核数据区读写函数。未实现 */

static int rw_kmem(int rw,char * buf, int count, off_t * pos)

{

return -EIO;

}

 

/* 端口读写操作函数,参数 : rw读写命令,buf缓冲区,count读写字节数,pos */

/* 端口地址,返回的是实际读写的字节数 */

static int rw_port(int rw,char * buf, int count, off_t * pos)

{

int i=*pos; // 端口地址

 

// 对于所要求读写的字节数,并且端口地址小于64k

while (count-->0 && i<65536) 

{

// 若是读命令,则从端口i 中读取一字节内容并放到用户缓冲区中

if (rw==READ)

put_fs_byte(inb(i),buf++);

// 若是写命令,则从用户数据缓冲区中取一字节输出到端口i

else

outb(get_fs_byte(buf++),i);

i++; // 前移一个端口

}

// 计算读/写的字节数,并相应调整读写指针

i -= *pos;

*pos += i;

// 返回读/写的字节数

return i;

}

 

/* 内存读写操作函数 */

static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos)

{

// 根据内存设备子设备号,分别调用不同的内存读写函数

switch(minor) 

{

case 0:

return rw_ram(rw,buf,count,pos);

case 1:

return rw_mem(rw,buf,count,pos);

case 2:

return rw_kmem(rw,buf,count,pos);

case 3:

return (rw==READ)?0:count; /* rw_null */

case 4:

return rw_port(rw,buf,count,pos);

default:

return -EIO;

}

}

 

/* 定义系统中设备种数 */

#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))

 

/* // 字符设备读写函数指针表,定义函数指针 */

static crw_ptr crw_table[]={

NULL, /* nodev */ /* 无设备(空设备) */

rw_memory, /* /dev/mem etc */ /* /dev/mem 等 */

NULL, /* /dev/fd */ /* /dev/fd 软驱 */

NULL, /* /dev/hd */ /* /dev/hd 硬盘 */

rw_ttyx, /* /dev/ttyx */ /* /dev/ttyx 串口终端 */

rw_tty, /* /dev/tty */ /* /dev/tty 终端 */

NULL, /* /dev/lp */ /* /dev/lp 打印机 */

NULL /* unnamed pipes */ /* 未命名管道 */

};

 

/* 字符设备读写操作函数,参数 : rw读写命令,dev设备号,buf缓冲区,count */

/* 读写字节数,pos读写指针,函数返回的是读写的字节数 */

int rw_char(int rw,int dev, char * buf, int count, off_t * pos)

{

crw_ptr call_addr;

 

// 如果设备号超出系统设备数,则返回出错码

if (MAJOR(dev)>=NRDEVS)

return -ENODEV;

// 若该设备没有对应的读/写函数,则返回出错码

if (!(call_addr=crw_table[MAJOR(dev)]))

return -ENODEV;

// 调用对应设备的读写操作函数,并返回实际读/写的字节数

return call_addr(rw,MINOR(dev),buf,count,pos);

}

参考《linux内核完全注释》和网上相关资料

抱歉!评论已关闭.