Newsgroups: comp.os.minix
Subject: Re: printf --> printk
References: <90ivfd$23on$1@msunews.cl.msu.edu>
Organization: Rochester Institute of Technology, Rochester, NY
From: aje9383@osfmail.isc.rit.edu (Andrew Erickson)
NNTP-Posting-Host: grace.isc.rit.edu
X-Original-NNTP-Posting-Host: grace.isc.rit.edu
Message-ID: <3a2d837d@news.isc.rit.edu>
Date: 5 Dec 2000 19:08:29 -0500
X-Trace: 5 Dec 2000 19:08:29 -0500, grace.isc.rit.edu
Lines: 86
XPident: aje9383
X-Original-NNTP-Posting-Host: 129.21.4.100
XPident: Unknown
Path: news.adfa.edu.au!clarion.carno.net.au!news0.optus.net.au!news1.optus.net.au!optus!intgwpad.nntp.telstra.net!newspump.monmouth.com!newspeer.monmouth.com!howland.erols.net!bloom-beacon.mit.edu!news.kodak.com!news-nysernet-16.sprintlink.net!news.sprintlink.net!news.isc.rit.edu!aje9383
Xref: news.adfa.edu.au comp.os.minix:36271

In article <90ivfd$23on$1@msunews.cl.msu.edu>,
Davis Ford <forddavi@msu.edu> wrote:
>I realize printf expands to printk in the source, but I need to do some
>logging and use the stdio.h print functions in the mm code.

<snipped text -- basically a user program calling a syscall which uses
printf/printk cannot have output redirected>

>I tried to circumvent this problem by going into alloc.c and doing #include
><stdio.h> at the top of the file, but this complained that it was redefining
>the printf -> printk function.  I can fix this by moving this #include
><stdio.h> down into my getholes( ) function only.  Now printf in this
>function should override the printf->printk function and I should be using
>the stdio printf - and theoretically should be able to redirect to a file
>using my userland program which makes the system call.  This did not work.
>Same thing happens.  I try:
>
># ./memstat >> memstat.txt
>
>It prints output of my system call getholes( ) to the console only.

Including the file later does not override the definition, because printf
becomes a macro in the kernel (I'm using "kernel" quite loosely, I know)
code.  The preprocessor simply replaces every instance of printf with
printk, including in the declarations in the header file.

>Next I tried opening a file and writing to that.  Again, I added the
>#include <stdio.h> to the getholes( ) function in alloc.c then I tried:
>
>FILE *out;
>
>if( (out = fopen("./tempfile", "a")) == NULL)
>    perror("fopen failed");
>else
>    printf("fopen ok\n");
>
>However, when I run the user program that makes the system call, it gets
>stuck at the if( (out = fopen("./tempfile", "a"))==NULL) - in fact it
>requires a hard reboot to fix it.

This is not surprizing; see below.

>Does anyone know HOW I can get mm code to either
>
>1) Write to a file for logging
>2) Figure out some way to redirect the output of a printf statement in
>system call that exists in MM code - call it from userland and redirect to a
>file

The primary problem here is that the standard I/O libraries cannot be used
from within the operating system proper (i.e. the kernel/mm/fs/inet stuff).
This is essentially because they rely on system calls to the OS to do their
stuff--fopen might be calling malloc, which calls sbrk or brk, and most
certainly calls open(); printf calls write() eventually; and so forth.  You
can't do that from within the OS mainly because it leads to deadlock under
many, many circumstances, or other equally problematic concerns.

You cannot redirect printk calls because they write data directly to the
console, bypassing the FS entirely.  (If you tried running your program
while logged into a terminal or telnetting from somewhere else, the output
would still appear on the console).  Actually, the core of teh OS doesn't
even know what standard output is, much less what redirection is; the FS
just sees it as anohter file descriptor, and attaches no special meaning to
the fact that it's descriptor number one or two or whichever.

The best solution is to somehow arrange to have your user-mode program do
the printing, where the standard I/O library exists and works and where the
output gets redirected.  How you get the data from the mm to your program is
up to you; probably the simplest and commonest approach is to (at the system
call level--this could be encapsulated into a library function with a
different interface) send a pointer to some chunk of memory in the system
call message and have the code in the memory manager fill it with the
information--in a manner somewhat analogous to what the read() system call
ends up doing.

At any rate, it is impossible to use many standard library functions in the
kernel.  (Specifically, it is only permissable to use those functions which
do not, directly or indirectly, call a system call.  This pretty much limits
the legal set to simplistic things, like string copies and compares,
mathematical functions, etc.; and many would argue that even some of these
are better left out or reimplemented, for various reasons)

Hope this helps.

-- 
Andrew Erickson
