一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

簡(jiǎn)化的字符設(shè)備驅(qū)動(dòng)程序scull

 danydany_ok 2010-11-30
先上一個(gè)簡(jiǎn)化過的例子
 
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h>  /* kmalloc() */
#include <linux/fs.h>  /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <asm/system.h>  /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include "scull.h"  /* local definitions */
/*
 * Our parameters which can be set at load time.
 */
int scull_major =   SCULL_MAJOR;
int scull_minor =   0;
int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */
int scull_quantum = SCULL_QUANTUM;
int scull_qset =    SCULL_QSET;
module_param(scull_major, int, S_IRUGO);
module_param(scull_minor, int, S_IRUGO);
module_param(scull_nr_devs, int, S_IRUGO);
module_param(scull_quantum, int, S_IRUGO);
module_param(scull_qset, int, S_IRUGO);
MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet");
MODULE_LICENSE("Dual BSD/GPL");
struct scull_dev *scull_devices; /* allocated in scull_init_module */

/*
 * Empty out the scull device; must be called with the device
 * semaphore held.
 */
int scull_trim(struct scull_dev *dev)
{
 struct scull_qset *next, *dptr;
 int qset = dev->qset;   /* "dev" is not-null */
 int i;
 for (dptr = dev->data; dptr; dptr = next) { /* all the list items */
  if (dptr->data) {
   for (i = 0; i < qset; i++)
    kfree(dptr->data[i]);
   kfree(dptr->data);
   dptr->data = NULL;
  }
  next = dptr->next;
  kfree(dptr);
 }
 dev->size = 0;
 dev->quantum = scull_quantum;
 dev->qset = scull_qset;
 dev->data = NULL;
 return 0;
}
/*
 * Open and close
 */
int scull_open(struct inode *inode, struct file *filp)
{
 struct scull_dev *dev; /* device information */
 dev = container_of(inode->i_cdev, struct scull_dev, cdev);
 filp->private_data = dev; /* for other methods */
 /* now trim to 0 the length of the device if open was write-only */
 if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {
  if (down_interruptible(&dev->sem))
   return -ERESTARTSYS;
  scull_trim(dev); /* ignore errors */
  up(&dev->sem);
 }
 return 0;          /* success */
}
int scull_release(struct inode *inode, struct file *filp)
{
 return 0;
}
/*
 * Follow the list
 */
struct scull_qset *scull_follow(struct scull_dev *dev, int n)
{
 struct scull_qset *qs = dev->data;
        /* Allocate first qset explicitly if need be */
 if (! qs) {
  qs = dev->data = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
  if (qs == NULL)
   return NULL;  /* Never mind */
  memset(qs, 0, sizeof(struct scull_qset));
 }
 /* Then follow the list */
 while (n--) {
  if (!qs->next) {
   qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
   if (qs->next == NULL)
    return NULL;  /* Never mind */
   memset(qs->next, 0, sizeof(struct scull_qset));
  }
  qs = qs->next;
  continue;
 }
 return qs;
}
/*
 * Data management: read and write
 */
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
                loff_t *f_pos)
{
 struct scull_dev *dev = filp->private_data;
 struct scull_qset *dptr; /* the first listitem */
 int quantum = dev->quantum, qset = dev->qset;
 int itemsize = quantum * qset; /* how many bytes in the listitem */
 int item, s_pos, q_pos, rest;
 ssize_t retval = 0;
 if (down_interruptible(&dev->sem))
  return -ERESTARTSYS;
 if (*f_pos >= dev->size)
  goto out;
 if (*f_pos + count > dev->size)
  count = dev->size - *f_pos;
 /* find listitem, qset index, and offset in the quantum */
 item = (long)*f_pos / itemsize;
 rest = (long)*f_pos % itemsize;
 s_pos = rest / quantum; q_pos = rest % quantum;
 /* follow the list up to the right position (defined elsewhere) */
 dptr = scull_follow(dev, item);
 if (dptr == NULL || !dptr->data || ! dptr->data[s_pos])
  goto out; /* don't fill holes */
 /* read only up to the end of this quantum */
 if (count > quantum - q_pos)
  count = quantum - q_pos;
 if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) {
  retval = -EFAULT;
  goto out;
 }
 *f_pos += count;
 retval = count;
  out:
 up(&dev->sem);
 return retval;
}
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
                loff_t *f_pos)
{
 struct scull_dev *dev = filp->private_data;
 struct scull_qset *dptr;
 int quantum = dev->quantum, qset = dev->qset;
 int itemsize = quantum * qset;
 int item, s_pos, q_pos, rest;
 ssize_t retval = -ENOMEM; /* value used in "goto out" statements */
 if (down_interruptible(&dev->sem))
  return -ERESTARTSYS;
 /* find listitem, qset index and offset in the quantum */
 item = (long)*f_pos / itemsize;
 rest = (long)*f_pos % itemsize;
 s_pos = rest / quantum; q_pos = rest % quantum;
 /* follow the list up to the right position */
 dptr = scull_follow(dev, item);
 if (dptr == NULL)
  goto out;
 if (!dptr->data) {
  dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);
  if (!dptr->data)
   goto out;
  memset(dptr->data, 0, qset * sizeof(char *));
 }
 if (!dptr->data[s_pos]) {
  dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
  if (!dptr->data[s_pos])
   goto out;
 }
 /* write only up to the end of this quantum */
 if (count > quantum - q_pos)
  count = quantum - q_pos;
 if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) {
  retval = -EFAULT;
  goto out;
 }
 *f_pos += count;
 retval = count;
        /* update the size */
 if (dev->size < *f_pos)
  dev->size = *f_pos;
  out:
 up(&dev->sem);
 return retval;
}
 
struct file_operations scull_fops = {
 .owner =    THIS_MODULE,
 .read =     scull_read,
 .write =    scull_write,
 .open =     scull_open,
 .release =  scull_release,
};
/*
 * Finally, the module stuff
 */
/*
 * The cleanup function is used to handle initialization failures as well.
 * Thefore, it must be careful to work correctly even if some of the items
 * have not been initialized
 */
void scull_cleanup_module(void)
{
 int i;
 dev_t devno = MKDEV(scull_major, scull_minor);
 /* Get rid of our char dev entries */
 if (scull_devices) {
  for (i = 0; i < scull_nr_devs; i++) {
   scull_trim(scull_devices + i);
   cdev_del(&scull_devices[i].cdev);
  }
  kfree(scull_devices);
 }
 /* cleanup_module is never called if registering failed */
 unregister_chrdev_region(devno, scull_nr_devs);
}

/*
 * Set up the char_dev structure for this device.
 */
static void scull_setup_cdev(struct scull_dev *dev, int index)
{
 int err, devno = MKDEV(scull_major, scull_minor + index);
   
 cdev_init(&dev->cdev, &scull_fops);
 dev->cdev.owner = THIS_MODULE;
 dev->cdev.ops = &scull_fops;
 err = cdev_add (&dev->cdev, devno, 1);
 /* Fail gracefully if need be */
 if (err)
  printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}

int scull_init_module(void)
{
 int result, i;
 dev_t dev = 0;
/*
 * Get a range of minor numbers to work with, asking for a dynamic
 * major unless directed otherwise at load time.
 */
 if (scull_major) {
  dev = MKDEV(scull_major, scull_minor);
  result = register_chrdev_region(dev, scull_nr_devs, "scull");
 } else {
  result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
    "scull");
  scull_major = MAJOR(dev);
 }
 if (result < 0) {
  printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
  return result;
 }
        /*
  * allocate the devices -- we can't have them static, as the number
  * can be specified at load time
  */
 scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
 if (!scull_devices) {
  result = -ENOMEM;
  goto fail;  /* Make this more graceful */
 }
 memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));
        /* Initialize each device. */
 for (i = 0; i < scull_nr_devs; i++) {
  scull_devices[i].quantum = scull_quantum;
  scull_devices[i].qset = scull_qset;
  init_MUTEX(&scull_devices[i].sem);
  scull_setup_cdev(&scull_devices[i], i);
 }
 return 0; /* succeed */
  fail:
 scull_cleanup_module();
 return result;
}
module_init(scull_init_module);
module_exit(scull_cleanup_module);
 
makefile文件依然用下面的
ARCH=arm
CROSS_COMPILE=arm-none-linux-gnueabi-
obj-m := scull.o
#   KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    KERNELDIR ?= /home/omap/linux-2.6.28-omap
    # The current directory is passed to sub-makes as argument
    PWD := $(shell pwd)
modules:   
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
 
modules_install:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
 
只是把.o文件改變了下。
[omap@localhost ldd3]$ make clean
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
[omap@localhost ldd3]$ make
make -C /home/omap/linux-2.6.28-omap M=/mnt/hgfs/linux_share/ldd3 modules
make[1]: Entering directory `/home/omap/linux-2.6.28-omap'
  CC [M]  /mnt/hgfs/linux_share/ldd3/scull.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /mnt/hgfs/linux_share/ldd3/scull.mod.o
  LD [M]  /mnt/hgfs/linux_share/ldd3/scull.ko
make[1]: Leaving directory `/home/omap/linux-2.6.28-omap'
[omap@localhost ldd3]$
 
放到devkit8000里面
[\u\@\h \W]# ls
hello.ko  scull.ko
[\u\@\h \W]# insmod scull.ko
[\u\@\h \W]# lsmod
scull 5228 0 - Live 0xbf000000
[\u\@\h \W]#
查看下主設(shè)備號(hào)
[\u\@\h \W]# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 81 video4linux
 89 i2c
 90 mtd
108 ppp
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
251 scull
252 hidraw
253 usb_endpoint
254 rtc
 
Block devices:
  1 ramdisk
259 blkext
  7 loop
  8 sd
 31 mtdblock
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
[\u\@\h \W]#
 
看到251 scull了吧,次設(shè)備號(hào)就是0,1,2,3了,一共4個(gè)設(shè)備。
于是
[\u\@\h \W]# mknod /dev/scull0 c 251 0
按照書本的提示來吃下內(nèi)存
cp /dev/zero /dev/scull0
開發(fā)板基本上就掛了。
 
換一種測(cè)試方式
[\u\@\h \W]# echo "hello" > /dev/scull0
[\u\@\h \W]# cat /dev/scull0
hello
[\u\@\h \W]#
 
這下就比較清晰了。
 
程序使用的是動(dòng)態(tài)分配主設(shè)備號(hào)的方法,實(shí)際使用時(shí)基本上都是使用的awk這類工具從/proc/devices中獲取信息,并在/dev目錄中創(chuàng)建設(shè)備文件。
 
下面這個(gè)名為scull_load的腳本是scull發(fā)布的一部分。我們可以在系統(tǒng)的rc.local文件中調(diào)用這個(gè)腳本或是在需要手工調(diào)用。
#!/bin/sh
# $Id: scull_load,v 1.4 2004/11/03 06:19:49 rubini Exp $
module="scull"
device="scull"
mode="664"
# Group: since distributions do it differently, look for wheel or use staff
if grep -q '^staff:' /etc/group; then
    group="staff"
else
    group="wheel"
fi
# invoke insmod with all arguments we got
# and use a pathname, as insmod doesn't look in . by default
/sbin/insmod ./$module.ko $* || exit 1
# retrieve major number
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
# Remove stale nodes and replace them, then give gid and perms
# Usually the script is shorter, it's scull that has several devices in it.
rm -f /dev/${device}[0-3]
mknod /dev/${device}0 c $major 0
mknod /dev/${device}1 c $major 1
mknod /dev/${device}2 c $major 2
mknod /dev/${device}3 c $major 3
ln -sf ${device}0 /dev/${device}
chgrp $group /dev/${device}[0-3]
chmod $mode  /dev/${device}[0-3]
 
卸載用下面的文件
#!/bin/sh
module="scull"
device="scull"
# invoke rmmod with all arguments we got
/sbin/rmmod $module $* || exit 1
# Remove stale nodes
rm -f /dev/${device} /dev/${device}[0-3]
 
在devkit8000上看下效果
[\u\@\h \W]# sh ./scull_load
[\u\@\h \W]# lsmod
scull 5228 0 - Live 0xbf004000
[\u\@\h \W]# ls -al /dev/scull*
lrwxrwxrwx    1 root     root            6 Jan  1 00:57 /dev/scull -> scull0
crw-rw-r--    1 root     wheel    251,   0 Jan  1 00:57 /dev/scull0
crw-rw-r--    1 root     wheel    251,   1 Jan  1 00:57 /dev/scull1
crw-rw-r--    1 root     wheel    251,   2 Jan  1 00:57 /dev/scull2
crw-rw-r--    1 root     wheel    251,   3 Jan  1 00:57 /dev/scull3
[\u\@\h \W]#
然后試下
[\u\@\h \W]# sh ./scull_unload
rmmod: module 'scull' not found
[\u\@\h \W]# lsmod
[\u\@\h \W]# ls -al /dev/scull*
ls: /dev/scull*: No such file or directory
[\u\@\h \W]#
 

 
 
 
 
 
 
 
 
 
 
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    国产精品免费无遮挡不卡视频| 国产丝袜极品黑色高跟鞋| 亚洲中文字幕在线观看四区 | 黑丝国产精品一区二区| 午夜精品一区免费视频| 亚洲欧美日韩在线看片| 日本亚洲欧美男人的天堂| 日本理论片午夜在线观看| 深夜福利亚洲高清性感| 国产熟女一区二区三区四区| 亚洲国产精品久久网午夜| 色哟哟在线免费一区二区三区| 成年女人午夜在线视频| 亚洲男人天堂网在线视频| 久久精品视频就在久久| 国产熟女一区二区三区四区| 国产亚洲欧美另类久久久| 欧美又黑又粗大又硬又爽| 最新午夜福利视频偷拍| 激情丁香激情五月婷婷| 一区二区福利在线视频| 国产成人精品视频一二区| 老司机精品线观看86| av中文字幕一区二区三区在线| 成在线人免费视频一区二区| 国产精品免费无遮挡不卡视频| 在线免费观看一二区视频| 成人国产一区二区三区精品麻豆| 久久福利视频视频一区二区| 欧美精品亚洲精品一区| 国产av天堂一区二区三区粉嫩| 日本亚洲精品在线观看| 91爽人人爽人人插人人爽| 东京干男人都知道的天堂| 六月丁香六月综合缴情| 激情三级在线观看视频| 亚洲av熟女国产一区二区三区站| 日本中文字幕在线精品| 欧美人与动牲交a精品| 欧美日韩精品综合一区| 久热香蕉精品视频在线播放|