免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4580 | 回复: 4
打印 上一主题 下一主题

tty设备驱动无read函数 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-28 11:49 |只看该作者 |倒序浏览
最近在看tty设备驱动,它的驱动操作里没有read函数,但是可以通过tty_flip_buffer_push函数将数据存到缓冲区。而用户要读tty设备缓冲区的数据可以在用户态下使用read系统调用,但是我使用read系统调用后,程序就不运行了,也没有结束,就是停在哪里不动了。
请问这是什么原因啊?

我的系统是ubuntu9.04.   内核版本是2.6.28

代码如下:
模块:
tty_lan_ops.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/tty.h>
#include <linux/fs.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/ioport.h>
#include <linux/serial_reg.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lan");

#define TTY_LAN_MINORS_NUM
5
#define TTY_LAN_MAJOR
202
static int open_count = 0;
static struct tty_driver *tty_lan_driver;

static int  tty_lan_open(struct tty_struct *tty, struct file *filp);
static void tty_lan_close(struct tty_struct *tty, struct file *filp);
static int  tty_lan_write(struct tty_struct *tty, const unsigned char *buffer, int count);
static int  tty_lan_write_room(struct tty_struct *tty);
static void tty_lan_set_termios(struct tty_struct *tty, struct ktermios * old);
static int  tty_lan_put_char(struct tty_struct *tty, unsigned char ch);

static struct tty_operations tty_lan_ops = {

.open = tty_lan_open,

.close = tty_lan_close,

.write = tty_lan_write,

.put_char = tty_lan_put_char,

.write_room = tty_lan_write_room,

.set_termios = tty_lan_set_termios,
};


static  int __init tty_lan_init(void)
{

int i;

int retval;



tty_lan_driver = alloc_tty_driver(TTY_LAN_MINORS_NUM);

if(!tty_lan_driver)

return -ENOMEM;



tty_lan_driver->owner = THIS_MODULE;

tty_lan_driver->driver_name = "tty_lan";

tty_lan_driver->name = "ttty_lan";

tty_lan_driver->major = TTY_LAN_MAJOR,

tty_lan_driver->minor_start = 0;


tty_lan_driver->type = TTY_DRIVER_TYPE_SERIAL;

tty_lan_driver->subtype = SERIAL_TYPE_NORMAL;

tty_lan_driver->flags = TTY_DRIVER_REAL_RAW;

tty_lan_driver->init_termios = tty_std_termios;

tty_lan_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;

tty_set_operations(tty_lan_driver, &tty_lan_ops);


retval = tty_register_driver(tty_lan_driver);

if(retval){

printk(KERN_ERR"Failed to register tty_lan_driver!\n");

put_tty_driver(tty_lan_driver);

return retval;

}


for(i = 0; i < TTY_LAN_MINORS_NUM; i++)

tty_register_device(tty_lan_driver, i, NULL);

return 0;
}

/*static struct tty_lan_serial{

struct tty_struct *tty;

int open_count;

struct semaphore sem;

struct timer_list *timer;
};*/

static int  tty_lan_open(struct tty_struct *tty, struct file *filp)
{

int i;

int data_size = 1;

char ch = '1';

if(open_count == 0){

printk("Open OK!\n");

}

for (i = 0; i < data_size; ++i) {

if (tty->count >= N_TTY_BUF_SIZE)

tty_flip_buffer_push(tty);

tty_insert_flip_char(tty, ch, TTY_NORMAL);

}

tty_flip_buffer_push(tty);


return 0;
}

static void tty_lan_close(struct tty_struct *tty, struct file *filp)
{

printk("ClOSE OK!\n");

return;
}

static int tty_lan_write(struct tty_struct *tty, const unsigned char *buffer, int count)
{

int retval = 0;

printk(KERN_DEBUG "%s - \n", __FUNCTION__);

printk("count :%d\n", count);

//for(i = 0; i < count; i++){

printk("user write: %s ", buffer);

//}

printk("\n");

return retval;
}

static int tty_lan_put_char(struct tty_struct *tty, unsigned char ch)
{

printk("put_char :%c\n", ch);

return 0;

}

static int  tty_lan_write_room(struct tty_struct *tty)
{

int room;

room = 255;

return room;
}

static void tty_lan_set_termios(struct tty_struct *tty, struct ktermios * old)
{

return ;
}

static void __exit tty_lan_exit(void)
{

int i;

for(i = 0; i < TTY_LAN_MINORS_NUM; i++)

tty_unregister_device(tty_lan_driver, i);

tty_unregister_driver(tty_lan_driver);
}

module_init(tty_lan_init);
module_exit(tty_lan_exit);

-----------------------------------------------------------------------------------------------------------------------------

Makefile:
UNAME = $(shell uname -r)
LINUX_PATH = /lib/modules/$(UNAME)/build
obj-m = tty_lan_ops.o
all:

$(MAKE) -C $(LINUX_PATH) M=$(PWD) modules
clean:


$(MAKE) -C $(LINUX_PATH) M=$(PWD) clean

rm Module.markers modules.order

-------------------------------------------------------------------------------------------------------------------------------

用户测试程序:
test.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int args, char *argv[])
{

int testdev;
   
int i, rf = 0;
   
char buf[15];

   
memset(buf, '\0', 15);
   
testdev = open("/dev/ttty_lan0", O_RDWR);
   
if(testdev == -1){
        
perror("open\n");
        
exit(0);
   
}
   
if((write(testdev, "111111111\0", 10)) < 0){
        
perror("Write error!\n");
        
exit(0);
   
}
   
close(testdev);
   
printf("write finish!\n");
   
testdev = open("/dev/ttty_lan0", O_RDWR);
   
rf = read(testdev, buf, 3);
   
if(rf < 0)
        
perror("read error\n");
   
printf("Read: %s\n", buf);
   
close(testdev);

   
return 0;
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

论坛徽章:
0
2 [报告]
发表于 2010-07-28 20:04 |只看该作者
用户程序调用read肯定会对于到对应文件的file_operation中的read函数,read函数会看tty_struct中的双缓冲区中是否有数据(如果是行缓冲就看是否有一行数据)。如果没有,就好被挂载到等待队列而阻塞。底层的驱动程序通过中断(不一定,可能是轮训)收到数据后就会调用tty_flip_buffer_push或类似的。tty_flip_buffer_push就会唤醒等待队列的所有进程,至于进程是否成功返回,要看它需要的条件是否满足

论坛徽章:
0
3 [报告]
发表于 2010-07-30 15:54 |只看该作者
回复 2# zhy-linux


   谢谢了。我明白了。

论坛徽章:
0
4 [报告]
发表于 2010-07-31 22:58 |只看该作者
非常感谢,学习了

论坛徽章:
0
5 [报告]
发表于 2014-06-16 05:32 |只看该作者
道理你明白了,但你程序的问题解决了吗?能读到数据了吗? 怎么解决的?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP