Linux 커널-간단한 문자 장치 scull

4777 단어
전언
Hello 프로그램의 컴파일을 통해 모두가 내장 모듈에 대해 이미 알고 있다고 믿습니다.다음은 어떻게 간단한 문자 장치를 실현하는지 소개할 것이다.먼저 사용자 디렉터리에 폴더 scull을 만듭니다. 세 개의 파일을 포함합니다: scull.c、Makefile、build
scull.c
#include 
#include 
#include  /* everything... */
#include 
#include  /* copy_*_user */
MODULE_LICENSE("GPL");
int scull_major = 0;
int scull_minor = 0;
struct cdev cdev; /* Char device structure */

#define MAX_SIZE 10
size_t size = 0;
char store[MAX_SIZE];
/*
* Open and close
*/
int scull_open(struct inode *inode , struct file *filp)
{
  /* trim to 0 the length of the device if open was write -only
  */
  if ( (filp ->f_flags & O_ACCMODE) == O_WRONLY) {
    size = 0;
  }
  return 0; /* success */
}
int scull_release(struct inode *inode , struct file *filp)
{
  return 0;
}
/*
* Data management: read and write
*/
ssize_t scull_read(struct file *filp , char __user *buf, size_t count, loff_t *f_pos)
{
  ssize_t retval = 0;
  if (*f_pos >= size)
    goto out;
  if (*f_pos + count > size)
    count = size - *f_pos;
  if (copy_to_user(buf, store + *f_pos , count)) {
    retval = -EFAULT;
    goto out;
  }
  *f_pos += count;
  retval = count;
out:
  return retval;
}
ssize_t scull_write(struct file *filp , const char __user *buf,size_t count ,loff_t *f_pos)
{
  ssize_t retval = -ENOMEM; /* value used in "goto out"
statements */
  if (*f_pos >= MAX_SIZE)
    goto out;
  if (*f_pos + count > MAX_SIZE)
    count = MAX_SIZE - *f_pos;
  if (copy_from_user(store + *f_pos , buf, count)) {
    retval = -EFAULT;
    goto out;
  }
  *f_pos += count;
  retval = count;
  /* update the size */
  if (size < *f_pos)
    size = *f_pos;
out:
  return retval;
}
struct file_operations scull_fops = {
  .owner = THIS_MODULE ,
  .read = scull_read ,
  .write = scull_write ,
  .open = scull_open ,
  .release = scull_release ,
};
int scull_init_module(void)
{
  int result;
  dev_t dev = 0;// linux  unsigned int   ,32 ,              , 12      , 20      
  /*
  * Get a range of minor numbers to work with , asking for a
  dynamic major
  */
  result = alloc_chrdev_region(&dev, scull_minor , 1, "scull");//       ,    "scull",    1,    scull_minor,          dev 。        0      。
  scull_major = MAJOR(dev);
  if (result < 0) {
    printk(KERN_WARNING "scull:?can't?get?major?%d
", scull_major); return result; } /* register our device */ cdev_init(&cdev , &scull_fops);// scull_fops cdev。 cdev.owner = THIS_MODULE; cdev.ops = &scull_fops; result = cdev_add (&cdev , dev, 1);// 。 if (result) { printk(KERN_WARNING "Error?%d?adding?scull", result) ; unregister_chrdev_region(dev, 1); return result; } return 0; /* succeed */ } void scull_cleanup_module(void) { /* cleanup_module is never called if registering failed */ dev_t dev; cdev_del(&cdev); dev = MKDEV(scull_major , scull_minor); unregister_chrdev_region(dev, 1); } module_init(scull_init_module); module_exit(scull_cleanup_module);

cdev 구조의 설명
struct cdev {
    struct kobject kobj;
    struct module *owner;//      
    const struct file_operations *ops;//      
    struct list_head list;
    dev_t dev; //   ,int   , 12      , 20      
    unsigned int count;
};

cdev_add (&cdev , dev, 1)
이것은 문자 장치에 장치를 추가하는 것입니다.구체적 실현 중인 kobjmap은 좀 복잡하고 관심 있는 건 스티브miao의 China Unix 블로그나 검색 관련 문제에 대한 깊은 연구.
read()와 write() 함수.
scull_read/scull_write(struct file *filp , char __user *buf, size_t count,loff_t *f_pos)
filp 파일 형식은 일반적으로 오픈 함수에서filp가 본 모듈의 파일 구조를 가리키지만 본고는 전역 변수를 사용하여filp를 사용하지 않습니다.buf는 읽을 곳,count는 읽을 개수, fops는 오프셋입니다.
copy_from_user 및 copyto_사용자의 함수 원형은strncpy입니다. 내부 핵과 사용자 권한 문제가 관련되어 봉인되어 있기 때문입니다.
build
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

Makefile
obj-m := scull.o

컴파일 마운트 모듈
컴파일링: 명령줄을 열고 다음 명령을 실행합니다.
cd scull
sh build

설치:
sudo insmod scull.ko //    scull.ko

등록된 장치를 보려면:
cat /proc/devices | grep scull

만약 아래의 정보와 유사하다면, 모든 것이 순조롭다는 것을 설명할 수 있다.그렇지 않으면 모듈 초기화에 오류가 발생했습니다./var/log/kern.log 구체적 상황 파악.
250 scull

장치 파일 만들기
sudo mknod /dev/scull c 250 0//          250

테스트
sudo su
echo 123 > /dev/scull
cat /dev/scull

출력 123을 보면 장치가 정상적으로 작동하고 있음을 증명합니다.
장치 제거
sudo rm /dev/scull
sudo rmmod scull

이번 문자 설비에 대해 진지하게 대처하고 관련 자료를 읽으며 각 함수의 기능, 파라미터의 작용을 이해하기 바랍니다. 이것은 앞으로의 실험에서 여러 번 사용될 것입니다.

좋은 웹페이지 즐겨찾기