|
又要麻烦各位大侠了
这是我的一段设备驱动程序(我是2.6的内核)
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <asm/uaccess.h> //for put_user()
- int init_module(void);
- void cleanup_module(void);
- static int device_open(struct inode *, struct file *);
- static int device_release(struct inode *, struct file *);
- static ssize_t device_read(struct file *, char *, size_t, loff_t *);
- //static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
- #define SUCCESS 0
- #define DEVICE_NAME "leo"
- #define BUFSZ 80
- char msg[BUFSZ];
- char *pmsg;
- static struct file_operations fops = {
- read : device_read,
- open : device_open,
- release : device_release
- };
- static int major;
- int init_module(void)
- {
- if((major=register_chrdev(0, DEVICE_NAME, &fops)) < 0){
- printk("Registering the character device failed with %d\n",major);
- return major;
- }
- printk("<1>I was assigned major number %d\n",major);
- return 0;
- }
- void cleanup_module(void)
- {
- int ret=unregister_chrdev(major, DEVICE_NAME);
- if(ret < 0)
- printk("Error in unregister_chrdev: %d\n", ret);
- }
- //called when a process tries to open the device file
- static int device_open(struct inode *inode, struct file *file)
- {
- try_module_get(THIS_MODULE);
- strcpy(msg, "Hello World!");
- pmsg = msg;
- return SUCCESS;
- }
- //called when a process closes the device file.
- static int device_release(struct inode *inode, struct file *file)
- {
- module_put(THIS_MODULE);
- return SUCCESS;
- }
- //called when a process already opened the dev file and attemts to read from it.
- static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
- {
- int bytes_read = 0;
- while ( length && *pmsg ){
- put_user(*pmsg++,buffer++);
- length--;
- bytes_read++;
- }
- return bytes_read;
- }
复制代码
重点不在驱动, 我把它编成模块,成功插入内核后,创建设备文件后,cat该设备文件,可以看到其内容。操作如下- # insmod ./chardev.ko
- # mknod testdriver c 253 0
- # cat testdriver
- Hello World!
复制代码
然后我用系统调用编了一个测试程序,如下- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #define DEV "/home/leo/test/os/driver/testdriver"
- int main()
- {
- int fd,bytes_read;
- char buf[100];
- if((fd = open(DEV, O_RDONLY)==-1)){
- perror("open device file");
- exit(1);
- }
- bytes_read=read(fd, buf, sizeof(buf));
- buf[bytes_read]=0;
- fprintf(stderr, "fd = %d, bytes_read = %d",fd, bytes_read);
- printf("Content Read: %s",buf);
- return 0;
- }
复制代码
运行到read就阻塞了, 我百思不得其解,后来用strace看了一下, 发现它竟然在读取标准输入!
- # strace ./a.out
- execve("./a.out", ["./a.out"], [/* 59 vars */]) = 0
- uname({sys="Linux", node="leo", ...}) = 0
- brk(0) = 0x804a000
- access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
- open("/etc/ld.so.cache", O_RDONLY) = 3
- fstat64(3, {st_mode=S_IFREG|0644, st_size=85545, ...}) = 0
- mmap2(NULL, 85545, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000
- close(3) = 0
- open("/lib/libc.so.6", O_RDONLY) = 3
- read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360P\1"..., 512) = 512
- fstat64(3, {st_mode=S_IFREG|0755, st_size=1295056, ...}) = 0
- mmap2(NULL, 1223980, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x4002d000
- mprotect(0x40151000, 27948, PROT_NONE) = 0
- mmap2(0x40152000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x124) = 0x40152000
- mmap2(0x40156000, 7468, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40156000
- close(3) = 0
- mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40158000
- mprotect(0x40152000, 4096, PROT_READ) = 0
- set_thread_area({entry_number:-1 -> 6, base_addr:0x40158a90, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
- munmap(0x40018000, 85545) = 0
- open("/dev/urandom", O_RDONLY) = 3
- read(3, "\354\256\242\210", 4) = 4
- close(3) = 0
- open("/home/leo/test/os/driver/testdriver", O_RDONLY) = 3
- read(0,
复制代码
我这才恍然大悟read为什么迟迟没有返回
后来我又用库函数重写了该测试程序,如下
- #include <stdio.h>
- #define DEV "/home/leo/test/os/driver/testdriver"
- int main()
- {
- FILE *fp;
- int bytes_read;
- char buf[100];
- if((fp = fopen(DEV, "r"))==NULL){
- perror("fopen device file");
- exit(1);
- }
- bytes_read=fread(buf, 1, sizeof(buf), fp);
- buf[bytes_read]=0;
- printf("bytes_read = %d, Content Read: %s",bytes_read,buf);
- return 0;
- }
复制代码 这样就一切正常了,看strace的输出- # strace ./a.out
- execve("./a.out", ["./a.out"], [/* 59 vars */]) = 0
- uname({sys="Linux", node="leo", ...}) = 0
- brk(0) = 0x804a000
- access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
- open("/etc/ld.so.cache", O_RDONLY) = 3
- fstat64(3, {st_mode=S_IFREG|0644, st_size=85545, ...}) = 0
- mmap2(NULL, 85545, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000
- close(3) = 0
- open("/lib/libc.so.6", O_RDONLY) = 3
- read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360P\1"..., 512) = 512
- fstat64(3, {st_mode=S_IFREG|0755, st_size=1295056, ...}) = 0
- mmap2(NULL, 1223980, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x4002d000
- mprotect(0x40151000, 27948, PROT_NONE) = 0
- mmap2(0x40152000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x124) = 0x40152000
- mmap2(0x40156000, 7468, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40156000
- close(3) = 0
- mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40158000
- mprotect(0x40152000, 4096, PROT_READ) = 0
- set_thread_area({entry_number:-1 -> 6, base_addr:0x40158a90, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
- munmap(0x40018000, 85545) = 0
- open("/dev/urandom", O_RDONLY) = 3
- read(3, "\226\224,\235", 4) = 4
- close(3) = 0
- brk(0) = 0x804a000
- brk(0x806b000) = 0x806b000
- open("/home/leo/test/os/driver/testdriver", O_RDONLY) = 3
- fstat64(3, {st_mode=S_IFCHR|0644, st_rdev=makedev(253, 0), ...}) = 0
- ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbffff23c) = -1 ENOTTY (Inappropriate ioctl for device)
- mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000
- read(3, "Hello World!", 4096) = 12
- read(3, "", 4096) = 0
- fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
- mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40019000
- write(1, "bytes_read = 12, Content Read: H"..., 43bytes_read = 12, Content Read: Hello World!) = 43
- munmap(0x40019000, 4096) = 0
- exit_group(0) = ?
复制代码
我一直搞不明白,为什么用系统调用读取设备文件时,read会被重定向到标准输入呢
各位大虾不吝赐教 |
|