linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* File access
@ 2003-08-14 11:32 Simon Haynes
  2003-08-14 12:07 ` Richard B. Johnson
  2003-08-14 12:19 ` Matti Aarnio
  0 siblings, 2 replies; 8+ messages in thread
From: Simon Haynes @ 2003-08-14 11:32 UTC (permalink / raw)
  To: linux-kernel

I am currently developing a module which I would like to configure
via a simple text file. 

I cannot seem to find any information on accessing files via a kernel module.

Is this possible and if so how is it done ?

Many Thanks

Simon.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-14 11:32 File access Simon Haynes
@ 2003-08-14 12:07 ` Richard B. Johnson
  2003-08-19  9:53   ` Simon Haynes
  2003-08-14 12:19 ` Matti Aarnio
  1 sibling, 1 reply; 8+ messages in thread
From: Richard B. Johnson @ 2003-08-14 12:07 UTC (permalink / raw)
  To: Simon Haynes; +Cc: linux-kernel

On Thu, 14 Aug 2003, Simon Haynes wrote:

> I am currently developing a module which I would like to configure
> via a simple text file.
>
> I cannot seem to find any information on accessing files via a kernel module.
>
> Is this possible and if so how is it done ?
>
> Many Thanks
>
> Simon.

This has become a FAQ. You make your module accept parameters
from an ioctl(). Then you use a user-mode task to read file(s)
and configure your module.


Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-14 11:32 File access Simon Haynes
  2003-08-14 12:07 ` Richard B. Johnson
@ 2003-08-14 12:19 ` Matti Aarnio
  2003-08-14 12:28   ` Muli Ben-Yehuda
  1 sibling, 1 reply; 8+ messages in thread
From: Matti Aarnio @ 2003-08-14 12:19 UTC (permalink / raw)
  To: Simon Haynes; +Cc: linux-kernel

On Thu, Aug 14, 2003 at 12:32:18PM +0100, Simon Haynes wrote:
> I am currently developing a module which I would like to configure
> via a simple text file. 
> 
> I cannot seem to find any information on accessing files via a kernel 
> module.
> 
> Is this possible and if so how is it done ?

  Yes, but it is rather complicated business, and really should not
  be done in kernel.   It can be done, but like Richard said, defining
  your own set of IOCTLs for the device is better.  The complicated
  configuration file parsing can then reside in the user-space utility
  program.

> Many Thanks
> Simon.

/Matti Aarnio

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-14 12:19 ` Matti Aarnio
@ 2003-08-14 12:28   ` Muli Ben-Yehuda
  0 siblings, 0 replies; 8+ messages in thread
From: Muli Ben-Yehuda @ 2003-08-14 12:28 UTC (permalink / raw)
  To: Simon Haynes; +Cc: Matti Aarnio, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1051 bytes --]

On Thu, Aug 14, 2003 at 03:19:17PM +0300, Matti Aarnio wrote:
> On Thu, Aug 14, 2003 at 12:32:18PM +0100, Simon Haynes wrote:
> > I am currently developing a module which I would like to configure
> > via a simple text file. 
> > 
> > I cannot seem to find any information on accessing files via a kernel 
> > module.
> > 
> > Is this possible and if so how is it done ?
> 
>   Yes, but it is rather complicated business, and really should not
>   be done in kernel.   It can be done, but like Richard said, defining
>   your own set of IOCTLs for the device is better.  The complicated
>   configuration file parsing can then reside in the user-space utility
>   program.

Indeed, do it in user space. But don't use ioctl unless it fits the
problem better than the other solutions. Use read / write on a device
file, or a special purpose file system, or sysfs, or even /proc. The
exact mechanism you should use depends on the nature of the user space
- kernel space communications. 
-- 
Muli Ben-Yehuda
http://www.mulix.org


[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-14 12:07 ` Richard B. Johnson
@ 2003-08-19  9:53   ` Simon Haynes
  2003-08-19 12:17     ` Richard B. Johnson
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Haynes @ 2003-08-19  9:53 UTC (permalink / raw)
  To: root; +Cc: linux-kernel

I actually had a character interface which I use for on the fly 
configuration. I have now implemented some code which uses a user process to 
pass the configuration to the driver. I have however run into problems trying 
to write files from the driver. I have tried implementing a user process 
which performs a blocking read. The user process is blocked with 
interruptible_sleep_on and is woken by the main part of the driver when it 
needs to write. The problem is I then need to stall the main part of the 
driver while the data gets written out. My problem is that this write needs 
to happen from an interrupt handler or a timer process. I cannot seem to 
block these with interruptible_sleep_on, the kernel crashes. I guess you 
cannot use this in these cases ? I have also tried semaphores without much 
success. I have looked for the howto but failed there also. 

Could you please tell me where I could find this FAQ.

Many Thanks

Simon.




On Thursday 14 Aug 2003 1:07 pm, Richard B. Johnson wrote:



> On Thu, 14 Aug 2003, Simon Haynes wrote:
> > I am currently developing a module which I would like to configure
> > via a simple text file.
> >
> > I cannot seem to find any information on accessing files via a kernel
> > module.
> >
> > Is this possible and if so how is it done ?
> >
> > Many Thanks
> >
> > Simon.
>
> This has become a FAQ. You make your module accept parameters
> from an ioctl(). Then you use a user-mode task to read file(s)
> and configure your module.
>
>
> Cheers,
> Dick Johnson
> Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
>             Note 96.31% of all statistics are fiction.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-19  9:53   ` Simon Haynes
@ 2003-08-19 12:17     ` Richard B. Johnson
  2003-08-19 13:36       ` Simon Haynes
  0 siblings, 1 reply; 8+ messages in thread
From: Richard B. Johnson @ 2003-08-19 12:17 UTC (permalink / raw)
  To: Simon Haynes; +Cc: linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1304 bytes --]

On Tue, 19 Aug 2003, Simon Haynes wrote:

> I actually had a character interface which I use for on the fly
> configuration. I have now implemented some code which uses a user process to
> pass the configuration to the driver. I have however run into problems trying
> to write files from the driver. I have tried implementing a user process
> which performs a blocking read. The user process is blocked with
> interruptible_sleep_on and is woken by the main part of the driver when it
> needs to write. The problem is I then need to stall the main part of the
> driver while the data gets written out. My problem is that this write needs
> to happen from an interrupt handler or a timer process. I cannot seem to
> block these with interruptible_sleep_on, the kernel crashes. I guess you
> cannot use this in these cases ? I have also tried semaphores without much
> success. I have looked for the howto but failed there also.
>
> Could you please tell me where I could find this FAQ.
>
> Many Thanks
>
> Simon.
>

You may want to post this somewhere. I don't have a web-page.
We are treated like prisoners here ;;;))   Just kidding, Thor
(network spy).

Cheers,
Dick Johnson


Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.


[-- Attachment #2: Type: TEXT/PLAIN, Size: 7036 bytes --]


File I/O from inside the kernel, FAQ............

As cited many times, the kernel is not a process. It is
designed to perform functions on behalf of a calling process.

Because it is not a process, it does not have a context.
A file descriptor without a context with which to associate
the file descriptor is worthless. For instance, all processes
are created with file descriptors, STDIN_FILENO, STDOUT_FILENO,
and STDERR_FILENO (0, 1, and 2), which are associated with some
I/O device. If these file-descriptor numbers were not associated
with a process context, every task would do I/O from the same
terminal.

At any instant, the context of a process is represented by
the object called "current". This, currently, is a pointer to
a structure which contains the elements necessary to resume
execution of the process when the kernel call returns. It also
contains the member values which uniquely define the process and
allow the kernel to perform tasks on behalf of the calling process.

To perform file I/O within the kernel requires a process context.
You can either steal one or you can create one. Stealing a process
context has the great potential of corrupting the task from which
you stole the context. This is because I/O would be performed into
its resources and you will very well overwrite buffered data
that that process is using.

Creating a process context involves creating a kernel thread. This
thread will function properly and can perform file I/O. However,
you can never use any C runtime library functions in the kernel so
you have to perform all primitive file I/O yourself. For instance,
you call sys_open(), you can never use open() or fopen(), etc.

Here is some module-code that starts up, then runs down a kernel-
thread. This is snipped from a module that I wrote so it is
incomplete, meant only as a template.


#ifndef __KERNEL__
#define __KERNEL__
#endif

#ifndef MODULE
#define MODULE
#endif

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <asm/delay.h>
#include <asm/io.h>
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *  This kernel thread runs forever as long as the module is installed.
 */
static int gpib_thread(void *unused)
{
    int doit;
    unsigned long flags;
    exit_files(current);
    daemonize();
    spin_lock_irq(&current->sigmask_lock);
    sigemptyset(&current->blocked);
    recalc_sigpending(current);
    spin_unlock_irq(&current->sigmask_lock);
    memcpy(current->comm, task_name, sizeof(task_name));
    DEB(printk("gpib_thread\n"));
    for(;;)
    { 
        // Kernel thread code goes here.



        if(!!signal_pending(current))
#ifdef NEW_THREAD_EXIT
            complete_and_exit(&info->quit, 0);
#else
            up_and_exit(&info->quit, 0);
#endif
    } 
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *   Initialize and register the module
 */
int __init init_module()
{
#ifdef NEW_THREAD_EXIT
    init_completion(&info->quit);
#else
    init_MUTEX_LOCKED(&info->quit);
#endif
    info->pid = kernel_thread(gpib_thread, NULL, CLONE_FS | CLONE_FILES);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *   Release the module.
 */
void cleanup_module()
{
        if(!!(result = kill_proc(info->pid, SIGTERM, 1)))
        {
            printk(A_sig, info->dev);
            return;
        }
#ifdef NEW_THREAD_EXIT
        wait_for_completion(&info->quit);
#else
        down(&info->quit);
#endif
}


Now, the only reason you would ever perform file I/O within the
kernel is as an "intellectual exercise". There is absolutely no
reason whatsoever to perform user-mode tasks within the kernel.

The way Unix/Linux is designed will always favor performing I/O
from user space. That's how it's supposed to be done with such
an Operating System. If you are actually designing something
that requires file I/O in the kernel, the design is __defective__.

There is only one Operating System that I know of in which there
was some performance to be gained by performing I/O from within
the kernel. That was VAX/VMS. Any such I/O was performed within
the context of the swapper process. The VAX/VMS kernel maintains
its own context. There are disadvantages, for instance every
interrupt generated a context-switch. There are advantages, the
interrupted task did not necessarily get the CPU back immediately
after an interrupt, etc.

The Unix model shares kernel code between all tasks, but the tasks
themselves get most of the CPU and are forced to give up the CPU
only when waiting for I/O or, in the case of a CPU-Hog, when a
context switch is forced by a timer.

If you need to read parameters from a file, when installing
a kernel module, you simply do this in user-space at the time
your user-space process installs the module. That's what ioctl()
functions are for. Also, even if you continually need to do file
I/O, you still do it from user-mode. Your kernel module just
does the things that can't be done from user-mode code.

If you need a user-mode response to an interrupt, it's easy.
Your user-mode code sleeps in select() or poll(). The driver/module
code does whatever is necessary to handle the immediate needs
of the hardware, then executes wake_up_interruptible(). This
wakes up your task and it processes the data received in the ISR.

There is no advantage running user-mode tasks within the kernel
because you have to do the same thing anyway. There is no way
for an interrupt to attach() or callback() a task. No real-world
Operating System uses interrupt "thunks", where some user gets
the CPU directly from an interrupt. This cannot happen because,
with no context-switch in an interrupt, there is no way to
return to the interrupted task. It cannot switch to another
task. If it did (by making some kernel changes), you would never
be able to get back to the original interrupted task.

Over and over again I have users state; "I MUST do file I/O in the
kernel...". This has always been a result of an incomplete 
understanding of what the kernel is and what the kernel does. Some
look at driver code and say; "It's just 'C' code. I can do this..."
Then they code a module and triple-fault the kernel.

The kernel is not a "high-performance" API where you can execute
some code with a performance advantage. The kernel is common-code
that can be executed by all tasks. That code is executed within
the context of the calling process. This makes it fast. The kernel
does file I/O through code that can't be modified by user tasks
so it follows the rules necessary to maintain file-systems. The
kernel, therefore, is a mechanism for maintaining the sanity of
a system. The actual work is done by the process itself.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-19 12:17     ` Richard B. Johnson
@ 2003-08-19 13:36       ` Simon Haynes
  2003-08-19 15:01         ` Richard B. Johnson
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Haynes @ 2003-08-19 13:36 UTC (permalink / raw)
  To: root; +Cc: linux-kernel

Thanks I have looked at the attached file and I would really not like to 
access a file from the kernel but I cannot seem to get the user land app to 
work with writing. If you consider a kernel module which, in some event, 
needs to save some information in a file. The usr app is blocked in a read 
with interruptible_sleep_on. When the first write occurs the module calls 
wake_up_interruptible to write the data. Before the module can write the next 
chunk of data it needs to stall until the user process has finished. 
I can not find a method of stalling the module so it seems my only solution 
is to write the file from the kernel or dump the data somewhere manually.

Cheers

Simon.  

On Tuesday 19 Aug 2003 1:17 pm, Richard B. Johnson wrote:
> On Tue, 19 Aug 2003, Simon Haynes wrote:
> > I actually had a character interface which I use for on the fly
> > configuration. I have now implemented some code which uses a user process
> > to pass the configuration to the driver. I have however run into problems
> > trying to write files from the driver. I have tried implementing a user
> > process which performs a blocking read. The user process is blocked with
> > interruptible_sleep_on and is woken by the main part of the driver when
> > it needs to write. The problem is I then need to stall the main part of
> > the driver while the data gets written out. My problem is that this write
> > needs to happen from an interrupt handler or a timer process. I cannot
> > seem to block these with interruptible_sleep_on, the kernel crashes. I
> > guess you cannot use this in these cases ? I have also tried semaphores
> > without much success. I have looked for the howto but failed there also.
> >
> > Could you please tell me where I could find this FAQ.
> >
> > Many Thanks
> >
> > Simon.
>
> You may want to post this somewhere. I don't have a web-page.
> We are treated like prisoners here ;;;))   Just kidding, Thor
> (network spy).
>
> Cheers,
> Dick Johnson
>
>
> Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
>             Note 96.31% of all statistics are fiction.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: File access
  2003-08-19 13:36       ` Simon Haynes
@ 2003-08-19 15:01         ` Richard B. Johnson
  0 siblings, 0 replies; 8+ messages in thread
From: Richard B. Johnson @ 2003-08-19 15:01 UTC (permalink / raw)
  To: Simon Haynes; +Cc: Linux kernel

On Tue, 19 Aug 2003, Simon Haynes wrote:

> Thanks I have looked at the attached file and I would really not like to
> access a file from the kernel but I cannot seem to get the user land app to
> work with writing. If you consider a kernel module which, in some event,
> needs to save some information in a file. The usr app is blocked in a read
> with interruptible_sleep_on. When the first write occurs the module calls
> wake_up_interruptible to write the data. Before the module can write the next
> chunk of data it needs to stall until the user process has finished.
> I can not find a method of stalling the module so it seems my only solution
> is to write the file from the kernel or dump the data somewhere manually.
>
> Cheers

No. SOP in user mode:
        pf.fd = fd;
        pf.revents = 0;
        pr.events  = POLLIN|OTHER_STUFF;
	if(poll(&pf, 1, NR) > 0)
            if(pf.revents & POLLIN))
                 read(fd, buf, BUF_LEN);

In the kernel module:

static wait_queue_head_t pwait;
static size_t global_poll;
static spinlock_t mylock;

// Remember to initialize both pwait and mylock;

static size_t poll(struct file *fp, struct poll_table_struct *wait)
{
    size_t poll_flag;
    size_t flags;
    poll_wait(fp, &pwait, wait);
    spin_lock_irqsave(&mylock, flags);
    poll_flag = global_poll | POLLRDNORM|POLLWRNORM;
    global_poll = 0;
    spin_lock_irqrestore(&mylock, flags);
    return poll_flag;
}

static void ISR(int irq, void *v, struct pt_regs *sp)
{
    spin_lock(&mylock);
    do_stuff_to_read_data_into_a_buffer();
    spin_unlock(&mylock);
    global_poll = POLLIN;
    wake_up_interruptible(&pwait);
}


So. You have a user-task sleeping in poll() or select().
The kernel is interrupted. It  calls your ISR where
you take data from wherever and put it into a buffer.
Then your ISR code, which knows that data are now available,
signals the sleeping task via wake_up_interruptible() and
then returns. The kernel scheduler now knows that your
task should be put into the run-queue and your task gets
the CPU via a return from poll(). You read the status
and now your task knows that data are available. Your
task calls read() to get the data.


There are no 'stalls'. You can be interrupted at any time.
Any time you switch buffers or manipulate pointers within
the module-code, where your code could get 'confused'
if an interrupt occurred, you use a spin-lock. This
prevents an interrupt from occurring at that time. You
release the lock as soon as it is safe to do so.

If data are streaming, you may need several buffers. You
need to synchronize your read() and the data source (the
ISR) so that old data are never overwritten. This, too, is
SOP. Just do it. It works. It's the basic stuff that makes
Unix work. There are lots of examples in the modules
supplied with the kernel sources.


Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2003-08-19 16:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-14 11:32 File access Simon Haynes
2003-08-14 12:07 ` Richard B. Johnson
2003-08-19  9:53   ` Simon Haynes
2003-08-19 12:17     ` Richard B. Johnson
2003-08-19 13:36       ` Simon Haynes
2003-08-19 15:01         ` Richard B. Johnson
2003-08-14 12:19 ` Matti Aarnio
2003-08-14 12:28   ` Muli Ben-Yehuda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).