c
复制代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/slab.h> // 包含这个头文件来使用 kmalloc 和 kfree
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#define DEVICE_NAME "mychar"
#define CLASS_NAME "mychar_class"
#define BUFFER_SIZE 1024
static int major;
static struct cdev *my_cdev;
static char *buffer;
static int buffer_size = BUFFER_SIZE;
static int mychar_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "mychar_open\n");
return 0;
}
static ssize_t mychar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
unsigned long p = *ppos;
unsigned int copy;
if (p >= buffer_size)
return 0;
if (count > buffer_size - p)
count = buffer_size - p;
if (copy_to_user(buf, buffer + p, count))
return -EFAULT;
*ppos += count;
return count;
}
static ssize_t mychar_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
unsigned long p = *ppos;
unsigned int copy;
if (p >= buffer_size)
return 0;
if (count > buffer_size - p)
count = buffer_size - p;
if (copy_from_user(buffer + p, buf, count))
return -EFAULT;
*ppos += count;
return count;
}
static loff_t mychar_llseek(struct file *file, loff_t offset, int whence) {
loff_t newpos = file->f_pos;
switch (whence) {
case SEEK_SET:
newpos = offset;
break;
case SEEK_CUR:
newpos += offset;
break;
case SEEK_END:
newpos = buffer_size + offset;
break;
default:
return -EINVAL;
}
if (newpos < 0 || newpos > buffer_size)
return -EINVAL;
file->f_pos = newpos;
return newpos;
}
static struct file_operations mychar_fops = {
.owner = THIS_MODULE,
.open = mychar_open,
.read = mychar_read,
.write = mychar_write,
// .llseek = mychar_llseek,
};
// 假设你有一个字符设备的私有数据结构
struct mychar_dev {
// ... 设备特定的数据 ...
char buffer[4096]; // 示例缓冲区
size_t buffer_pos; // 示例缓冲区中的当前位置
};
static struct mychar_dev mychar_device;
// /proc 文件的读取处理函数
static ssize_t mychar_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
size_t len;
if (*ppos >= sizeof(mychar_device.buffer) || count == 0)
return 0;
len = min(count, sizeof(mychar_device.buffer) - (size_t)*ppos);
if (copy_to_user(buf, mychar_device.buffer + *ppos, len))
return -EFAULT;
*ppos += len;
return len;
}
// /proc 文件的写入处理函数
static ssize_t mychar_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
size_t len;
if (*ppos >= sizeof(mychar_device.buffer) || count == 0)
return 0;
len = min(count, sizeof(mychar_device.buffer) - (size_t)*ppos);
if (copy_from_user(mychar_device.buffer + *ppos, buf, len))
return -EFAULT;
// 更新设备缓冲区的位置(如果需要的话)
// 这里我们简单地增加偏移量,但你可以根据需要进行更复杂的处理
*ppos += len;
// 注意:在实际的设备驱动中,你可能需要同步缓冲区到硬件或执行其他操作
return len;
}
// /proc 文件的 file_operations 结构体
static const struct file_operations mychar_proc_fops = {
.owner = THIS_MODULE,
.read = mychar_proc_read,
.write = mychar_proc_write,
// 注意:没有 open 和 release,因为 /proc 文件系统的处理是自动的
// 也没有 llseek,因为 /proc 文件通常不支持随机访问
};
static struct class *mychar_class;
static struct proc_dir_entry *mychar_proc_entry;
static int __init mychar_init(void) {
int err;
dev_t devno = MKDEV(major, 0);
if (major) {
my_cdev = cdev_alloc();
my_cdev->owner = THIS_MODULE;
my_cdev->ops = &mychar_fops;
my_cdev->dev = devno;
err = cdev_add(my_cdev, MKDEV(major, 0), 1);
if (err) {
printk(KERN_NOTICE "Error %d adding mychar", err);
return err;
}
} else {
err = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
if (err < 0) {
printk(KERN_NOTICE "Error %d registering character device", err);
return err;
}
major = MAJOR(devno);
my_cdev = cdev_alloc();
my_cdev->owner = THIS_MODULE;
my_cdev->ops = &mychar_fops;
my_cdev->dev = devno;
err = cdev_add(my_cdev, MKDEV(major, 0), 1);
if (err) {
unregister_chrdev_region(MKDEV(major, 0), 1);
printk(KERN_NOTICE "Error %d adding mychar", err);
return err;
}
}
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!buffer) {
cdev_del(my_cdev);
unregister_chrdev_region(MKDEV(major, 0), 1);
printk(KERN_NOTICE "Failed to allocate device buffer\n");
return -ENOMEM;
}
// 创建设备类
mychar_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(mychar_class)) {
printk(KERN_WARNING "Failed to register device class\n");
cdev_del(my_cdev);
unregister_chrdev_region(MKDEV(major, 0), 1);
kfree(buffer);
return PTR_ERR(mychar_class);
}
// 创建设备
device_create(mychar_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
// 创建 /proc 文件
mychar_proc_entry = proc_create("mychar", 0666, NULL, &mychar_proc_fops);
if (!mychar_proc_entry) {
pr_err("Failed to create /proc/mychar\n");
return -ENOMEM; // 或者其他适当的错误码
}
printk(KERN_INFO "mychar device registered with major number %d\n", major);
return 0;
}
static void __exit mychar_exit(void) {
device_destroy(mychar_class, MKDEV(major, 0));
class_destroy(mychar_class);
cdev_del(my_cdev);
unregister_chrdev_region(MKDEV(major, 0), 1);
kfree(buffer);
if (mychar_proc_entry) {
remove_proc_entry("mychar", NULL);
}
printk(KERN_INFO "mychar device unregistered\n");
}
module_init(mychar_init);
module_exit(mychar_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver");
c
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define BUFFER_SIZE 2048 // 定义缓冲区大小
int main(int argc, char *argv[]) {
int fd;
ssize_t ret;
off_t pos;
char buffer[BUFFER_SIZE];
// 假设 fd 已经被正确打开
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open failed");
return EXIT_FAILURE;
}
// 首次读取(可能不需要,但根据原始代码保留)
ret = read(fd, buffer, 0); // 这里传递 0 字节,实际上不会读取任何内容
if (ret != 0) {
perror("Unexpected read return");
close(fd);
return EXIT_FAILURE;
}
printf("***********read ret=%d\n", ret);
// 重置文件位置
pos = lseek(fd, 0, SEEK_SET);
if (pos < 0) {
perror("lseek failed");
close(fd);
return EXIT_FAILURE;
}
printf("***********lseek pos=%d\n", (int)pos);
// 清理缓冲区(虽然在这个场景下可能不是必需的)
memset(buffer, 0, BUFFER_SIZE);
// 读取文件内容到缓冲区
ret = read(fd, buffer, BUFFER_SIZE);
if (ret < 0) {
perror("read failed");
close(fd);
return EXIT_FAILURE;
}
printf("***********read ret=%d\n", ret);
// 检查是否读取了足够的数据来检查换行符
if (ret < (ssize_t)(BUFFER_SIZE >> 1)) {
char *bptr = buffer;
// 查找换行符
while (*bptr && *bptr != '\n') {
bptr++;
}
if (*bptr == '\n') {
const off_t offset = 2 + (bptr - buffer);
printf("***********offset=%d\n", (int)offset);
// 跳转到换行符后的位置
pos = lseek(fd, offset, SEEK_SET);
if (pos == (off_t)-1) {
perror("lseek failed");
close(fd);
return EXIT_FAILURE;
}
printf("***********lseek pos=%d\n", (int)pos);
// 从新位置读取(如果需要)
// 注意:这里可能需要额外的逻辑来决定是否再次读取
// 这里仅作为示例,不实际读取
ret = read(fd, buffer, BUFFER_SIZE);
printf("***********read ret=%d\n", ret);
// (void)ret;
}
}
off_t dec;
pos = lseek(fd, 0, SEEK_END);
printf("***********lseek pos=%d\n", (int)pos);
if (pos < 0)
return EXIT_FAILURE;
dec = pos / 13;
printf("***********dec=%d\n", (int)dec);
if (dec < 1)
dec = 1;
while (pos > 0) {
off_t seek_pos;
seek_pos = lseek(fd, pos, SEEK_SET);
printf("***********lseek seek_pos=%d\n", (int)seek_pos);
if (seek_pos < 0)
break;
ret = read(fd, buffer, 5);
printf("***********read ret=%d\n", ret);
(void)ret;
if (dec > pos)
dec = pos;
pos -= dec;
}
// 关闭文件描述符
close(fd);
return EXIT_SUCCESS;
}
c
复制代码
#include <stdio.h>
#include <dirent.h>
int main(int argc,char* argv[],char* envp[]) {
struct dirent **namelist;
printf("argc=%d, argv[0]=%s, argv[1]=%s\n", argc, argv[0], argv[1]);
int numEntries = scandir(argv[1], &namelist, NULL, alphasort);
if (numEntries < 0) {
perror("scandir");
} else {
for (int i = 0; i < numEntries; i++) {
printf("File %d: %s\n", i, namelist[i]->d_name);
}
}
// 释放动态分配的内存
for (int i = 0; i < numEntries; i++) {
free(namelist[i]);
}
free(namelist);
return 0;
}