一般我们在user space 通过open打开某个字符设备,例如下面的函数就会打开/dev/i2c-x 这个字符设备
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
{
int file;
snprintf(filename, size, "/dev/i2c-%d", i2cbus);
filename[size - 1] = '\0';
file = open(filename, O_RDWR);
if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
sprintf(filename, "/dev/i2c-%d", i2cbus);
file = open(filename, O_RDWR);
}
return file;
}
假如已经有/dev/i2c-0.和/dev/i2c-1,这个使用我用ln -sf /dev/i2c-1 /dev/i2c-0.这个时候再用open函数来打开/dev/i2c-0 是open的/dev/i2c-0 还是/dev/i2c-1 呢?
先把结论告诉大家,open的是/dev/i2c-1。原因如下:
do_sys_open->do_filp_open->path_openat
在path_openat 中有一段关键的code如下:
while (!(error = link_path_walk(s, nd)) &&
(error = do_last(nd, file, op, &opened)) > 0) {
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
s = trailing_symlink(nd);
if (IS_ERR(s)) {
error = PTR_ERR(s);
break;
}
}
这段code中会调用trailing_symlink 来检查当前打开的文件,例如本例子中的/dev/i2c-1 是否是符号链接,如果是符号链接的话
static const char *trailing_symlink(struct nameidata *nd)
{
const char *s;
int error = may_follow_link(nd);
if (unlikely(error))
return ERR_PTR(error);
nd->flags |= LOOKUP_PARENT;
nd->stack[0].name = NULL;
s = get_link(nd);
return s ? s : "";
}
会调用may_follow_link 来检查是否有权限来得到符号链接的真实链接,本例中由于是root 用户,肯定和是有权限的,因此这里就找到/dev/i2c-1 指向的真实链接/dev/i2c-0
假如open的文件是个符号链接
最新推荐文章于 2022-05-21 16:52:54 发布