Kernel 在内核空间中从STDIN读取数据
我正试图为Kernel 在内核空间中从STDIN读取数据,kernel,freebsd,system-calls,Kernel,Freebsd,System Calls,我正试图为FreeBSD 9.3.0编写一个内核模块,我想在其中使用read系统调用。我已包括适当的标题(除其他外): #包括 #包括 #包括 #包括 #包括 但是,当我运行make时,会出现以下错误: 函数的隐式声明read 我还查看了上述标题的源文件,并在sys/sys和sys/kern中搜索了大量源代码树,以查找上述函数,但我找不到它。 注意:我可以从同一个程序成功使用printfsystemcall。(编译时没有read调用) 更新:文档实际声明包括unistd.h。但是这是在C标准库
FreeBSD 9.3.0
编写一个内核模块,我想在其中使用read
系统调用。我已包括适当的标题(除其他外):
#包括
#包括
#包括
#包括
#包括
但是,当我运行make时,会出现以下错误:
函数的隐式声明read
我还查看了上述标题的源文件,并在sys/sys
和sys/kern
中搜索了大量源代码树,以查找上述函数,但我找不到它。
注意:我可以从同一个程序成功使用printf
systemcall。(编译时没有read
调用)
更新:文档实际声明包括
unistd.h
。但是这是在C标准库中,我不能在内核中使用它。所以问题变成了,我还有什么其他的选择?(我试着从STDIN
)读取我同意@qarma的观点,即代表用户进程在内核空间执行读取有点奇怪-用户空间应该发出自己的读取调用,特别是当您在内核模式下运行时,所有的安全检查和进程策略检查都在窗口之外,以及进程记帐、统计等。内核模式在处理数据和访问时需要格外小心
有很多更好的方法可以将数据进出内核模块。提到一个:
如果您想了解如何正确处理驱动程序中的文件,
看看pf(4)如何使用用户空间帮助程序pfctl(8)来
读取配置文件并将其转换为二进制数据
然后通过/dev/pf将其馈送到内核驱动程序的结构
装置
或者,您可以使用用户模式程序将数据从磁盘/etc加载到某个缓冲区中,并执行ioctl以获取数据;不过,读写/dev/MyDriver端点可能更好
如果您真的发现自己需要完全按照您的要求去做,那么同一篇文章指出至少内核的某些部分会写入文件系统-进程coredumpper-文章指向kern/kern_sig.c
,例如:
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\u open
打开文件,将其作为输出vp
和vname
,其中vp
是指向vnode对象的指针
深入到corefile\u 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\u open\u cred
——完成后,我们可以使用新初始化的nd.ni\u vp
变量来获取我们的vnode指针。注意对NDINIT和NDFREE的调用
如果需要,您可以深入了解更多-vfs\u cnops.c
包含vn\u open\u 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\u open\u cred
您正在尝试做一些非常奇怪的事情。在内核中调用read
的目的是什么?您是否代表用户这样做?数据将被放入userland缓冲区吗?是的,数据将被发送到userland。(这是一个赋值)如果您想做的是在数据到达用户的应用程序之前从用户的tty设备读取数据,那么编写一个行规程可能会更容易。
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);