Date: Fri, 30 Mar 2001 09:45:05 -0500 (EST) From: Robert Watson <rwatson@FreeBSD.ORG> To: Gurpratap Virdi <gvirdi@gvirdi.com> Cc: hackers@FreeBSD.ORG Subject: Re: Writing to a file in the kernel Message-ID: <Pine.NEB.3.96L.1010330093326.96088h-100000@fledge.watson.org> In-Reply-To: <001501c0b923$51754e10$8d7d1f26@dhgfhcpps5nhe1>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 30 Mar 2001, Gurpratap Virdi wrote: > I am trying to debug some modifications I made to the kernel. I would > like to write some debug messages to a log file however fopen(), > fprint() don't work. It gives me a linking error when I try to use them. > How can I do this? Thanks in advance! There are two techniques normally used for customized logging in the kernel. (1) The first is to create a /dev/myfavoritelogdevice, and queue messages there for a userland daemon to pick up, possibly filter or process, and spit into a file. This is much what syslog does with kernel messages, as well as various incarnations of auditing support, pccardd, and other kernel event-driven daemons. In this scenario, you borrow a major device number, and implement a queueing facility in kernel for the device. Depending on the properties you want, the queue might be bounded or un-bounded. When reads occur on the device, you spit one line out at a time to the userland process. Take a look at src/sys/kern/subr_log.c for an example of such a device. (2) The second is for the kernel to write directly to a file. In such situations, the file to log to is generally indicated by a userland process, and pathnames are generally only meaningful in the context of a particular process (in fact, namei() requires a process to function, as that's where it gets its notion of "root" and "working" directories). There are a number of examples of this process, including support for accounting, quotas, UFS extended attributes, and even core dumps. Some process-driven event (often a syscall) indicates to the kernel which file to send things to, the kernel performs a vn_open() (or appropriate VOP_OPEN() and other activities) on the passed name, and on success, returns success on the syscall but keeps the file open. Writes are then made using vn_rw() or VOP_WRITE(). Most examples of this are relatively complex, but this may be the closest match to what you are looking for -- this is a lot simpler if you just open, write, close based on a single userland-initiated event, than if you want a persisting open file. Take a look at the implementation of quotactl(), and ufs_quotactl(), as well as extattrctl() and ufs_extattrctl(), both of which open a file based on a userland administration syscall, and then keep the file open for later reading and writing. Both preserve the credential of the process at the time of open() for use during writing (remember to crhold() the credential reference, or it might get garbage-collected out from under you). In order to write to a vnode, you also need to have a current struct proc for scheduling in the event that sleeping is required. This means that you can't do VOP's from interrupt context, except in -CURRENT where, due to SMPng, interrupt threads have enough context to sleep (yay!). When you're done with the log file, remember to close it and release the right number of vnode references. If you fail to close it, it is possible that changes written to the file might not be appropriately flushed on some file systems. For example, AFS and Coda both have a "flush on close" semantic, so a failure to close means a failure to flush :-). If you're just using UFS, you're probably OK. Robert N M Watson FreeBSD Core Team, TrustedBSD Project robert@fledge.watson.org NAI Labs, Safeport Network Services To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1010330093326.96088h-100000>