跟上回一样,我用这个小程序来读
#include
<
stdio.h
>
#include
<
fcntl.h
>
#include
<
unistd.h
>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
int
main()
...
{
char*name="/sys/bus/ldd/version";
charbuf[500];
intfd;
intsize;
fd=open(name,O_RDONLY);
printf("fd:%d ",fd);
size=read(fd,buf,sizeof(buf));
printf("size:%d ",size);
printf("%s",buf);
close(fd);
return-1;
}
(1)sysfs_open_file()
open() ->/*用户空间*/
-> 系统调用->
sys_open() -> filp_open()-> dentry_open() -> sysfs_open_file()/*内核空间*/
static int sysfs_open_file(struct inode * inode, struct file * filp)
{
return check_perm(inode,filp);
}
static
int
check_perm(
struct
inode
*
inode,
struct
file
*
file)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
...
{
structkobject*kobj=sysfs_get_kobject(file->f_dentry->d_parent);
structattribute*attr=to_attr(file->f_dentry);
structsysfs_buffer*buffer;
structsysfs_ops*ops=NULL;
interror=0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if(!kobj||!attr)
gotoEinval;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*Grabthemodulereferenceforthisattributeifwehaveone*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if(!try_module_get(attr->owner))...{
error=-ENODEV;
gotoDone;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*ifthekobjecthasnoktype,thenweassumethatitisasubsystem
*itself,anduseopsforit.
*/
if(kobj->kset&&kobj->kset->ktype)
ops=kobj->kset->ktype->sysfs_ops;
elseif(kobj->ktype)
ops=kobj->ktype->sysfs_ops;
else
ops=&subsys_sysfs_ops;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*Nosysfsoperations,eitherfromhavingnosubsystem,
*orthesubsystemhavenooperations.
*/
if(!ops)
gotoEaccess;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*Fileneedswritesupport.
*Theinode'spermsmustsayit'sok,
*andwemusthaveastoremethod.
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if(file->f_mode&FMODE_WRITE)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if(!(inode->i_mode&S_IWUGO)||!ops->store)
gotoEaccess;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*Fileneedsreadsupport.
*Theinode'spermsmustsayit'sok,andwethere
*mustbeashowmethodforit.
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if(file->f_mode&FMODE_READ)...{
if(!(inode->i_mode&S_IRUGO)||!ops->show)
gotoEaccess;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*Noerror?Great,allocateabufferforthefile,andstoreit
*itinfile->private_dataforeasyaccess.
*/
buffer=kmalloc(sizeof(structsysfs_buffer),GFP_KERNEL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if(buffer)...{
memset(buffer,0,sizeof(structsysfs_buffer));
init_MUTEX(&buffer->sem);
buffer->needs_read_fill=1;
buffer->ops=ops;
file->private_data=buffer;
}else
error=-ENOMEM;
gotoDone;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Einval:
error=-EINVAL;
gotoDone;
Eaccess:
error=-EACCES;
module_put(attr->owner);
Done:
if(error&&kobj)
kobject_put(kobj);
returnerror;
}
check_perm()检查一下权限,创建一个sysfs的缓冲区sysfs_buffer buffer,并设置其sysfs_ops sysfs_buffer->ops。在我们这个故事里,sysfs_buffer->ops被设置成bus_sysfs_ops。最后让file->private_data = buffer。
(2)sysfs read file()
流程如下:
read()->/*用户空间*/
-> 系统调用->
sys_read() -> vfs_read() -> sysfs_read_file()/*内核空间*/
看看sysfs_read_file()函数,
static
ssize_t
sysfs_read_file(
struct
file
*
file,
char
__user
*
buf,size_tcount,loff_t
*
ppos)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
...
{
structsysfs_buffer*buffer=file->private_data;
ssize_tretval=0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
down(&buffer->sem);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if(buffer->needs_read_fill)...{
if((retval=fill_read_buffer(file->f_dentry,buffer)))
gotoout;
}
pr_debug("%s:count=%d,ppos=%lld,buf=%s ",
__FUNCTION__,count,*ppos,buffer->page);
retval=flush_read_buffer(buffer,buf,count,ppos);
out:
up(&buffer->sem);
returnretval;
}
顺着sysfs_read_file()往下走:
sysfs_read_file()
---> fill_read_buffer()
---> sysfs_buffer->bus_sysfs_ops->bus_attr_show()
---> bus_attribute->show_bus_version() //注意这个函数是我们在lddbus.c里面定义的
---> flush_read_buffer()
fill_read_buffer()的是真正的读,它把内容读到sysfs定义的缓冲区sysfs_buffer。flush_read_buffer()是把缓冲区copy到用户空间。详细内容我就不贴了。