KDD 문자 장치 기본 개념
include/linux/cdev.h
12 struct cdev {
13 struct kobject kobj;
14 struct module *owner;
15 const struct file_operations *ops;
16 struct list_head list;
17 dev_t dev;
18 unsigned int count;
19 };
include/linux/fs.h
518 /*
519 * Keep mostly read-only and often accessed (especially for
520 * the RCU path lookup and 'stat' data) fields at the beginning
521 * of the 'struct inode'
522 */
523 struct inode {
595 union {
596 struct pipe_inode_info *i_pipe;
597 struct block_device *i_bdev;
598 struct cdev *i_cdev;
599 };
612 };
include/linux/fs.h
765 struct file {
777 struct inode *f_inode; /* cached value */
800 /* needed for tty driver, and maybe others */
801 void *private_data;
812 };
struct cdev 는 문자 장치, ops 는 파일 조작 함수, dev 는 장치 번호 입 니 다.
// include/linux/cdev.h
struct cdev {
struct module *owner;
const struct file_operations *ops;
dev_t dev;
// ......
};
cdev 와 ops 와 관련 된 함 수 는 cdevinit:
void cdev_init(struct cdev *, const struct file_operations *);
cdev 와 dev 에 관 한 함 수 는 cdev 입 니 다.add, 즉 문자 장치 추가:
int cdev_add(struct cdev *, dev_t, unsigned);
문자 장 치 를 추가 하면 mknod 로 파일 을 만 들 수 있 고 읽 고 쓸 수 있 습 니 다.
장치 번 호 를 만 들 때 장치 이름, 즉 함수 alloc 를 지정 해 야 합 니 다.chrdev_region。
mknod 는 장치 이름과 장치 번 호 를 알 아야 합 니 다. 구동 을 설치 한 후 / proc / devices 에서 장치 이름 에 따라 장치 번 호 를 찾 을 수 있 습 니 다.
insmod hello.ko \
&& major_device_number=`awk '$2=="winlin" {print $1}' /proc/devices` \
&& mknod /dev/winlin c $major_device_number 0
파일 을 만 들 면 이 파일 / dev / winlin 을 읽 고 쓸 수 있 습 니 다.
cat /dev/winlin \
&& echo "linux is a great operating system for server." > /dev/winlin \
&& cat /dev/winlin
마지막 으로 장치 와 드라이브 삭제:
rm -f /dev/winlin \
&& rmmod hello
전체 원본 코드 는 다음 과 같 습 니 다.
// hello.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
dev_t devno;
int count = 1;
char* name = "winlin";
/**
make
insmod hello.ko \
&& major_device_number=`awk '$2=="winlin" {print $1}' /proc/devices` \
&& mknod /dev/winlin c $major_device_number 0
cat /dev/winlin \
&& echo "linux is a great operating system for server." > /dev/winlin \
&& cat /dev/winlin
rm -f /dev/winlin \
&& rmmod hello
*/
/*module_param(count, int, S_IRUGO|S_IWUSR);*/
module_param(name, charp, S_IRUGO|S_IWUSR);
#include <linux/fs.h>
#include <linux/uaccess.h>
char _data[1024] = "KDD char device buffer.
";
ssize_t hello_read(struct file* file,
char __user* data, size_t size, loff_t* offset
){
int len = strlen(_data);
if(*offset >= len){
return 0;
}
printk(KERN_ALERT
"hello_read, len=%d, size=%d, offset=%d
",
len, (int)size, (int)*offset);
if(copy_to_user(data, _data, (len < size)? len:size) != 0){
return -1;
}
*offset += len;
return len;
}
ssize_t hello_write(struct file* file,
const char __user* data, size_t size, loff_t* offset
){
int size_to_write = (sizeof(_data) - 1 < size)? sizeof(_data) - 1:size;
printk(KERN_ALERT
"hello_write, len=%d, size=%d, offset=%d
",
size_to_write, (int)size, (int)*offset);
if(copy_from_user(_data, data, size_to_write) != 0){
return -1;
}
_data[size_to_write] = 0;
return size_to_write;
}
int hello_open(struct inode* node, struct file* file){
return 0;
}
int hello_release(struct inode* node, struct file* file){
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release,
};
#include <linux/cdev.h>
struct cdev dev;
int hello_init(void){
printk(KERN_INFO "hello, %s!
", name);
if(alloc_chrdev_region(&devno, 0, count, name) != 0){
return -1;
}
cdev_init(&dev, &fops);
dev.owner = THIS_MODULE;
//dev.ops = &fops;
if(cdev_add(&dev, devno, 1) != 0){
return -1;
}
return 0;
}
void hello_exit(void){
printk(KERN_ALERT "goodbye, %s
", name);
unregister_chrdev_region(devno, count);
}
module_init(hello_init);
module_exit(hello_exit);
Makefile 은 다음 과 같 습 니 다:
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.mod.* *.ko *.order *.symvers *.o
endif
하나의 구동 은 minor 가 다 르 고 major 와 같은 여러 장 치 를 만 들 수 있 습 니 다.코드 는 다음 과 같 습 니 다:
// hello.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
int major = 0;
int count = 1;
char* name = "winlin";
/**
make
insmod hello.ko count=2\
&& major_device_number=`awk '$2=="winlin" {print $1}' /proc/devices` \
&& mknod /dev/winlin0 c $major_device_number 0 \
&& mknod /dev/winlin1 c $major_device_number 1
cat /dev/winlin0 \
&& echo "[dev0] linux is a great operating system for server." > /dev/winlin0 \
&& cat /dev/winlin0
cat /dev/winlin1 \
&& echo "[dev1] linux is a great operating system for server." > /dev/winlin1 \
&& cat /dev/winlin1
rm -f /dev/winlin* \
&& rmmod hello
*/
module_param(count, int, S_IRUGO|S_IWUSR);
module_param(name, charp, S_IRUGO|S_IWUSR);
#include <linux/fs.h>
#include <linux/uaccess.h>
char _data[1024] = "KDD char device buffer.
";
ssize_t hello_read(struct file* file,
char __user* data, size_t size, loff_t* offset
){
int len = strlen(_data);
if(*offset >= len){
return 0;
}
printk(KERN_ALERT
"hello_read, len=%d, size=%d, offset=%d
",
len, (int)size, (int)*offset);
if(copy_to_user(data, _data, (len < size)? len:size) != 0){
return -1;
}
*offset += len;
return len;
}
ssize_t hello_write(struct file* file,
const char __user* data, size_t size, loff_t* offset
){
int size_to_write = (sizeof(_data) - 1 < size)? sizeof(_data) - 1:size;
printk(KERN_ALERT
"hello_write, len=%d, size=%d, offset=%d
",
size_to_write, (int)size, (int)*offset);
if(copy_from_user(_data, data, size_to_write) != 0){
return -1;
}
_data[size_to_write] = 0;
return size_to_write;
}
int hello_open(struct inode* node, struct file* file){
printk(KERN_ALERT "hello_open file
");
return 0;
}
int hello_release(struct inode* node, struct file* file){
printk(KERN_ALERT "hello_release file
");
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release,
};
#include <linux/cdev.h>
struct cdev dev;
int hello_init(void){
int i;
dev_t devno;
printk(KERN_INFO "hello, %s!
", name);
if(alloc_chrdev_region(&devno, 0, count, name) != 0){
return -1;
}
major = MAJOR(devno);
cdev_init(&dev, &fops);
dev.owner = THIS_MODULE;
//dev.ops = &fops;
for(i = 0; i < count; i++){
if(cdev_add(&dev, MKDEV(major, i), 1) != 0){
return -1;
}
}
return 0;
}
void hello_exit(void){
printk(KERN_ALERT "goodbye, %s
", name);
cdev_del(&dev);
unregister_chrdev_region(MKDEV(major, 0), count);
}
module_init(hello_init);
module_exit(hello_exit);
이 두 장 치 는 모두 하나의 cdev 와 data 를 공유 하여 모든 장치 에 서로 다른 표 시 를 할 수 있 습 니 다. 즉, count 에 따라 구조 체 를 열 수 있 습 니 다. 이 구조 체 는 cdev 와 data 를 포함 합 니 다.
코드 는 다음 과 같 습 니 다:
// hello.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
int major = 0;
int count = 1;
char* name = "winlin";
/**
make
insmod hello.ko count=2\
&& major_device_number=`awk '$2=="winlin" {print $1}' /proc/devices` \
&& mknod /dev/winlin0 c $major_device_number 0 \
&& mknod /dev/winlin1 c $major_device_number 1
cat /dev/winlin0 \
&& echo "[dev0] linux is a great operating system for server." > /dev/winlin0 \
&& cat /dev/winlin0
cat /dev/winlin1 \
&& echo "[dev1] linux is a great operating system for server." > /dev/winlin1 \
&& cat /dev/winlin1
rm -f /dev/winlin* \
&& rmmod hello
*/
module_param(count, int, S_IRUGO|S_IWUSR);
module_param(name, charp, S_IRUGO|S_IWUSR);
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/cdev.h>
struct winlin_dev{
dev_t devno;
char data[1024];
struct cdev cdev;
};
const char* msg = "KDD char device buffer.
";
struct winlin_dev* devs;
ssize_t hello_read(struct file* file,
char __user* data, size_t size, loff_t* offset
){
struct winlin_dev* dev = file->private_data;
int len = strlen(dev->data);
if(*offset >= len){
return 0;
}
printk(KERN_ALERT
"hello_read, len=%d, size=%d, offset=%d
",
len, (int)size, (int)*offset);
if(copy_to_user(data, dev->data, (len < size)? len:size) != 0){
return -1;
}
*offset += len;
return len;
}
ssize_t hello_write(struct file* file,
const char __user* data, size_t size, loff_t* offset
){
struct winlin_dev* dev = file->private_data;
int size_to_write = (sizeof(dev->data) - 1 < size)? sizeof(dev->data) - 1:size;
printk(KERN_ALERT
"hello_write, len=%d, size=%d, offset=%d
",
size_to_write, (int)size, (int)*offset);
if(copy_from_user(dev->data, data, size_to_write) != 0){
return -1;
}
dev->data[size_to_write] = 0;
return size_to_write;
}
int hello_open(struct inode* node, struct file* file){
struct winlin_dev* dev = container_of(node->i_cdev, struct winlin_dev, cdev);
file->private_data = dev;
return 0;
}
int hello_release(struct inode* node, struct file* file){
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release,
};
int hello_init(void){
int i;
dev_t devno;
printk(KERN_INFO "hello, %s!
", name);
if(alloc_chrdev_region(&devno, 0, count, name) != 0){
return -1;
}
major = MAJOR(devno);
devs = kmalloc(count * sizeof(struct winlin_dev), GFP_KERNEL);
if(!devs){
return -1;
}
memset(devs, 0, count * sizeof(struct winlin_dev));
for(i = 0; i < count; i++){
cdev_init(&devs[i].cdev, &fops);
devs[i].cdev.owner = THIS_MODULE;
//devs[i].cdev.ops = &fops;
devs[i].devno = MKDEV(major, i);
if(cdev_add(&devs[i].cdev, devs[i].devno, 1) != 0){
return -1;
}
memcpy(devs[i].data, msg, strlen(msg));
}
return 0;
}
void hello_exit(void){
int i;
printk(KERN_ALERT "goodbye, %s
", name);
for(i = 0; i < count; i++){
cdev_del(&devs[i].cdev);
}
kfree(devs);
unregister_chrdev_region(MKDEV(major, 0), count);
}
module_init(hello_init);
module_exit(hello_exit);
Makefile 변경:
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.mod.* *.ko *.order *.symvers *.o
install:
bash install.sh
uninstall:
rm -f /dev/winlin*
rmmod hello
endif
설치 스 크 립 트:
#!/bin/bash
#install.sh
insmod hello.ko count=2
major_device_number=`cat /proc/devices|grep winlin|awk '{print $1}'`
mknod /dev/winlin0 c ${major_device_number} 0
mknod /dev/winlin1 c ${major_device_number} 1
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.