linux驱动程序3.18,Demo 驱动程序——Linux-2.6.18.3

环境:

操作系统:Federo core 6

内核版本:Linux-2.6.18.3

步骤:

1.安装内核

FC6操作系统自带的内核不是标准内核,内核源码有些文件没有。所以下载Linux-2.6.18.3版本的内核并安装。

1)将内核源码包拷贝到/usr/src/kernels目录下,解压。

# tar –zxvf linux-2.6.18.3.tar.gz

2) 进入源码根目录,配置内核,编译内核,编译内核模块,安装内核模块,安装内核

# make menuconfig

#make dep

#make bzImage

#make modules

#make modules_install

#make install

3)重新启动系统,在Grub中可以看到多了一个选项,选择Linux-2.6.18.3版本的内核启动系统。

2.Linux-2.6 与 Linux-2.4设备驱动程序的不同

Linux-2.6版本较之Linux-2.4版本的内核模块有很多的不同点,从设备管理的方式到许多系统函数的名称都有很多改变。内核模块的基本结构还是一样的。具体的不同点见http://net.stuun.cn/system/Linux/45194.html 中内核操作 Linux2.6内核驱动移植参考一文。在这主要说一下Linux-2.6下的设备管理——udev。在Linux-2.6种用udev代替了devfs管理设备。udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。udev依赖于sysfs文件系统提供的信息。

3.编写demo驱动程序

驱动程序功能:在内核空间开辟一块内存空间,实现open ,write,ioctl,release 操作,写入字符串后将字符串顺序反转。

Demo程序源码:

//内核头文件定义

#include

#include

#include

#include

#include

#include

#include

#define DEVICE_NAME "demo"

MODULE_LICENSE("Dual BSD/GPL");

struct demo_dev

{

char buffer[1024];

int curpos;

struct cdev cdev;

};

static struct demo_dev * demo_device;

static int demo_major=0; //主设备编号

static int demo_minor=0; //次设备编号

//将字符串内字符顺序反转

static void do_write(struct demo_dev *dev)

{

printk("do_write\n");

if(dev != NULL)

{

int i;

int len = dev->curpos;

char tmp;

printk("change \n");

for(i = 0; i < (len>>1); i++,len--)

{

tmp = dev->buffer[len-1];

dev->buffer[len-1] = dev->buffer[i];

dev->buffer[i] = tmp;

printk("%c %c\n",dev->buffer[i],dev->buffer[len-1]);

}

}

}

//demo驱动写操作

static int demo_write(struct file * filp,const char * buffer,

size_t count,loff_t * ppos)

{

int retval=0;

struct demo_dev *dev = filp->private_data;

if(dev->curpos + count > 1024)

{

count = 1024 - dev->curpos;

}

if(copy_from_user(dev->buffer + dev->curpos,buffer,count))

{

retval = -EFAULT;

goto out;

}

dev->curpos+=count;

*ppos=dev->curpos;

retval = count;

do_write(dev);

out:

return retval;

}

//demo 驱动读操作

static int demo_read(struct file * filp,char * buffer,

size_t count,loff_t * ppos)

{

int retval=0;

struct demo_dev *dev=filp->private_data;

printk("demo:read \n");

printk("demo pos %d   count %d \n",*ppos,count);

if(*ppos >= dev->curpos) goto out;

if((*ppos) + count > dev->curpos)

count = dev->curpos - *ppos ;

if(copy_to_user(buffer,dev->buffer ,14))

{

retval = -EFAULT;

goto out;

}

*ppos+=count;

retval=count;

out:

return retval;

}

//demo 驱动ioctl操作

static int demo_ioctl(struct inode * inode,struct file * filp,

unsigned int cmd,unsigned long arg)

{

printk("ioctl running\n");

switch(cmd)

{

case 1: printk("command 1         \n");break;

case 2: printk("command 2         \n");break;

default:

printk("error cmd\n");

}

return 0;

}

//demo 驱动open操作

static int demo_open(struct inode * inode,struct file * filp)

{

struct demo_dev *dev;

dev=container_of(inode->i_cdev,struct demo_dev,cdev);

filp->private_data = dev;

printk("demo:open success\n");

return 0;

}

//demo 驱动release

static int demo_release(struct inode * inode,struct file * filp)

{

printk("demo:release success\n");

return 0;

}

//demo驱动文件操作结构体

static struct file_operations demo_fops={

.owner = THIS_MODULE,

.read = demo_read,

.write = demo_write,

.ioctl = demo_ioctl,

.open = demo_open,

.release = demo_release,

};

//demo 驱动初始化

static int demo_init(void)

{

dev_t dev;

int result=0;

printk("demo init\n");

if(demo_major)

{

dev=MKDEV(demo_major,demo_minor);

result=register_chrdev_region(dev,1,DEVICE_NAME); //静态注册

}

else

{

result=alloc_chrdev_region(&dev,demo_minor,1,DEVICE_NAME); //动态注册

demo_major=MAJOR(dev);

}

if(result < 0)

{

printk(KERN_WARNING"demo:can't get major %d\n",demo_major);

return result;

}

demo_device = (struct demo_dev *)kmalloc(sizeof(struct demo_dev),GFP_KERNEL);

if(demo_device == NULL)

{

result= -ENOMEM;

goto fail;

}

memset(demo_device,0,sizeof(struct demo_dev));

cdev_init(&demo_device->cdev,&demo_fops);

demo_device->cdev.owner = THIS_MODULE;

demo_device->cdev.ops   = &demo_fops;

if(cdev_add(&demo_device->cdev,dev,1))

{

printk(KERN_NOTICE"Error adding scull");

}

printk("demo initialized\n");

return 0;

fail:

unregister_chrdev_region(dev,1);

return result;

}

//demo 驱动退出

static void demo_exit(void)

{

cdev_del(&demo_device->cdev);

kfree(demo_device);

unregister_chrdev_region(MKDEV(demo_major,demo_minor),1);

printk("demo exited\n");

}

module_init(demo_init);

module_exit(demo_exit);

Makefile编写:

obj-m := demo-26.o

编译模块:

#make -C /lib/modules/`uname -r`/build M=`pwd` modules

在/sysfs或/proc目录中查看设备信息,用mknod在/dev下建立设备节点。

4.编写测试程序,编译运行。

写入:abcdefghijk

输出:kjihgfedcba

结果正确。

(victor_tlh)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值