我正在设计一个仅读取和写入字符缓冲区的设备驱动程序。但是我的问题是关于file_operations
结构read
和中的两个功能write
。我不真正了解真正的含义loff_t *offp
。我知道对于读取和写入操作而言,这*offp
都是文件偏移量,即文件的当前读取/写入位置,但是我什至不知道对设备文件进行读写是什么意思。
从我收集的数据来看,这就是我在设备上进行写入和读取的方式,是我创建了一个表示我所称设备的结构,该结构在my_char_struct
下面显示。
struct my_char_structure{
struct cdev my_cdev;
struct semaphore sem;
char *data;
ssize_t data_size;
unsigned int access_key;
unsigned long size;
};
这是一个静态结构,在我的驱动程序本身处于初始化状态时会被初始化并指向该结构insmod
。
static dev_t dev_num;
static struct my_char_structure Dev;
int start_mod(void){
//Because we are dealing with a fictitious device, I want
//the driver to create my two devices with arbitrarily
//assigned major numbers.
struct my_char_structure *my_dev = &Dev;
int err;
alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);
sema_init(&(my_dev->sem),1);
cdev_init(&(my_dev->my_cdev), &fops);
my_dev->my_cdev.owner = THIS_MODULE;
my_dev->my_cdev.ops = &fops;// fops is my file operations struct
err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);
if(err<0)
printk(KERN_ALERT "There was an error %d.",err);
printk(KERN_ALERT " insmod to major number %d",MAJOR(dev_num));
return 0;
}
module_init(start_mod);
当我的设备打开时,我只是打开了一个指向文件的指针,以指向在此过程中设置的静态结构module_init(start_mod)
…
int dev_open(struct inode *in_node, struct file *filp){
static struct my_char_structure *my_dev;
my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);
printk(KERN_ALERT "The device number is %d",iminor(in_node));
if(!my_dev)
printk(KERN_ALERT "something didn't work. my_dev not initialized.");
filp->private_data = my_dev;
return 0;
}
我的读写方法所做的就是修改打开的文件所指向的初始结构Dev。无论我copy_to_user
从我的结构是什么样的用户认为被写入到该设备并不管我copy_from_user
的用户认为他们正在写。但是除了更改我的初始结构Dev之外,文件位置或偏移量的概念没有任何意义,除非它指向内核中某个任意结构或类型的缓冲内存的指针。多数民众赞成在我对文件偏移量的唯一解释…这是正确的吗?这是loff_t *offp
这里所指的吗?
write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
(假设我的理解是正确的)当调用了一些诸如读/写之类的file_operation并且我没有*offp
亲自设置时,loff_t * offp最初设置为什么?
如果在最后一个file_operation中offp =
some_arbitrary_address(因为我这样告诉我),那么当再次调用此操作时,offp将设置为什么?
如果我正在运行其他file_opens操作,它将设置为上次file_operation保留的状态,还是会保留使用的file_open操作的选项卡,并将*
offp替换为file_open使用的内容,会发生什么情况?
char设备的概念对我来说太抽象了,它看起来设备本身甚至不像文件那样存储信息,而是存储信息的驱动程序。我希望我已经解释了我的模糊感,并且会清理掉我似乎不清楚的所有内容。
“参数loff_t”是一个“长偏移量”,即寻求立场相结合的疯狂多样性off_t
,off64_t
等,使驾驶者可以只使用参数loff_t,而不是担心。
当您进入驱动程序时,指针本身指向用户提供的偏移量(假设它是用户代码来执行驱动程序访问,从技术上讲内核可以提供自己的偏移量,但是用户的情况就是要考虑的情况)通过lseek
,llseek
或lseek64
等等,然后通过普通的读写操作。考虑一下常规磁盘文件的情况:当您首次创建open
文件时,您(作为用户)将获得内核以提供一个数据结构,该数据结构可跟踪您在文件中的当前位置,因此,如果您read
或write
某些字节,下一个read
或write
从您上次停站的地方接站。
此外,如果你dup
文件描述符,或做通过(例如)的等效fork
和exec
运行命令的序列而言,该寻找位置由所有继承进程共享。因此,在shell提示符下,命令:
(prog1; prog2; prog3) > outputfile
创建一个输出文件,然后dup
将描述符传递给这三个程序,以便prog2
写入的输出在的输出之后立即进入该文件prog1
,而输出的结果prog3
紧随其他两个之后—都是因为所有三个单独的进程共享相同的基础内核数据结构具有相同的内部loff_t
。
这同样适用于设备驱动程序文件。调用读取和写入函数时,您会收到用户提供的“当前偏移量”,并且可以(并且应该)根据需要对其进行更新…假设有任何需要(例如,您想为用户提供常规文件的外观,包括在读取和写入时偏移量会移动的事实)。如果设备在逻辑上应用了查找偏移,则可以在此处使用它。
当然,设备驱动程序还有很多,这就是为什么在此书(qv)上有整本书的章节。:-)
问题内容: 我不太清楚该在哪里抛出该异常。 例如,我正在实现接口,并且不希望任何人调用该方法: Future#get(long,TimeUnit)。 所以,我可以扔吗? 事情是方法的规范并没有说明抛出异常。反过来,例外 抛出以指示不支持请求的操作。 类UnsupportedOperationException 我的意思是,如果您不希望调用它,通常会抛出它,否则可能会因为不是所有方法都已实现而被认为
问题内容: 我试图了解Go中的并发性。特别是,我编写了以下线程不安全程序: 我认识到我应该使用渠道来防止与发生竞争,但这不是重点。程序打印,然后似乎永远循环(不再打印任何内容)。我希望它能打印出无限的数字列表,可能由于竞态条件而跳过某些数字并重复其他数字(或更糟的是,在更新数字时打印数字)。 我的问题是:为什么程序只打印一行? 只是要清楚一点:对于这个玩具示例,我不是故意使用渠道。 问题答案: 关
问题内容: 我了解这是一个框架;甚至还有一个开源的跨平台游戏开发库。我转到libgdx主页,并按照视频教程中的说明进行操作。正确设置项目后,我可以在多个受支持的平台上运行默认的my- gdx-game项目。太好了,花花公子…现在呢? 我一直在搜索论坛,Wiki,javadocs和许多其他站点,以寻找体面的简单操作方法。不幸的是,我找不到任何东西,那里的大多数帮助都假设您对这个库有一些基本的了解。
问题内容: JNDI就像是类固醇的地图,对吗?我使用键来查找对对象的引用。另外,什么是InitialContext?我似乎不知道这个主意。 问题答案: 从概念上讲,JNDI就像类固醇。 允许您从命令行将参数传递给代码。同样,JNDI允许您在代码外部(例如,在应用程序服务器配置文件中)配置任意对象,然后在代码中使用它们。 换句话说,它是Service Locator模式 的实现:您的代码从中心注册表
问题内容: 我正在尝试使用触发两个请求,然后在两个请求完成后调用一些函数。这是我的代码: 但是,这没有按预期方式工作。Ajax调用将返回要在其中使用的数据,而Ajax调用将返回要分配给var count并随后在中使用的count 。 但是,当我启动上面的代码时,先被调用,然后再将数据保留为as 。我如何才能做到这一点,据我所知,只有当两个返回的函数都执行时,才能进行。我希望两个ajax调用都应该并
问题内容: 我遇到了“ 高级Linux编程”中的 一个概念。这里是一个链接:请参阅 4.5 GNU / Linux线程实现 。 我对作者所说的概念很清楚,但是我对他解释的为线程打印processID的程序感到困惑。 这是代码 根据作者,上述代码的输出为 我编译时得到的输出是 我知道,创建线程时,Linux内部调用 clone (大多数情况下),就像 fork 系统调用创建进程一样。唯一的区别是在进