我正在尝试为FreeBSD 9.3.0
编写内核模块,我想在其中使用read
Syscall。我已经包含了相应的标题(以及其他标题):
#include<sys/sysproto.h>
#include<sys/unistd.h>
#include<sys/types.h>
#include<sys/uio.h>
#include<sys/cdefs.h>
但是当我运行make时,我收到以下错误:
隐式声明函数
read
我还查看了所述标题的源文件,并搜索了sys/sys
和sys/kern
中的很多源代码树,寻找所述函数,但我无法找到它。
注意:我可以成功使用同一程序中的printf
系统调用。(没有read
调用编译)
更新:文档实际上声明包含unistd.h
。但是那个在C标准库中,我不能在内核中使用它。所以问题变成了这个,我还有其他什么选择? (我试图从STDIN
读取)
答案 0 :(得分:3)
我同意@qarma认为在内核空间中代表用户进程执行读取有点奇怪 - 用户空间应该发出自己的读取调用,特别是因为所有的安全检查和处理当您在内核模式下运行时,策略检查不在窗口,以及进程记帐,统计等。内核模式在处理数据和访问时需要非常小心。
有更好的方法可以将数据输入和输出内核模块。 This post on the FreeBSD forums提到一个:
如果您想了解如何正确处理驱动程序中的文件, 看看pf(4)如何使用用户空间助手程序pfctl(8)来实现 读取配置文件并将其转换为二进制数据 然后通过/ dev / pf将结果提供给内核驱动程序 设备
或者,您可以使用用户模式程序将数据从磁盘/等加载到某个缓冲区并执行ioctl以获取数据;但是,读/写/ dev / MyDriver端点可能更好。
如果您确实发现自己需要完全按照您的要求进行操作,那么相同的帖子表明内核的至少某些部分写入文件系统 - 进程coredumper - 帖子指向kern/kern_sig.c
as一个例子:
static int
coredump(struct thread *td)
{
struct proc *p = td->td_proc;
struct ucred *cred = td->td_ucred;
struct vnode *vp;
struct flock lf;
struct vattr vattr;
int error, error1, locked;
struct mount *mp;
char *name; /* name of corefile */
off_t limit;
int compress;
...
error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, compress, &vp, &name);
coredump
调用corefile_open
打开文件,将其作为输出vp
和vname
,其中vp
是指向vnode对象的指针。
深入研究corefile_open
,我们看到:
static int
corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
int compress, struct vnode **vpp, char **namep)
{
struct nameidata nd;
struct sbuf sb;
const char *format;
char *hostname, *name;
int indexpos, i, error, cmode, flags, oflags;
...
flags = O_CREAT | FWRITE | O_NOFOLLOW;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, NULL);
...
NDFREE(&nd, NDF_ONLY_PNBUF);
*vpp = nd.ni_vp;
注意对vn_open_cred
的调用 - 完成后,我们可以使用刚刚初始化的nd.ni_vp
变量来获取我们的vnode指针。请注意对NDINIT和NDFREE的调用。
如果您愿意,可以挖掘更多内容 - vfs_cnops.c
包含vn_open_cred
的实现,可能看起来很熟悉:
int
vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags,
struct ucred *cred, struct file *fp)
{
struct vnode *vp;
struct mount *mp;
struct thread *td = ndp->ni_cnd.cn_thread;
struct vattr vat;
struct vattr *vap = &vat;
int fmode, error;
... lots of setup ...
error = vn_open_vnode(vp, fmode, cred, td, fp);
你有它 - vn_open_vnode终于完成了真正的工作。
你最好的选择可能是vn_open_cred
。