2

For my assignment I need to read some strings coming from a serial port. This has to be done in a kernel module, so I can't use stdio library. I'm trying in this way:

#include <linux/module.h>
#include <linux/unistd.h>
#include <asm/io.h>
#include <asm/fcntl.h>
#define SERIAL_PORT "/dev/ttyACM0"

void myfun(void){
  int fd = open(SERIAL_PORT,O_RDONLY | O_NOCTTY);
  ..reading...

}

but it gives me "implicit declaration of function open"

user1610075
  • 1,583
  • 3
  • 15
  • 32

3 Answers3

2

You want to use the filp_open() function, it is pretty much a helper to open a file in kernelspace. You can find the man on it here

The file pointer from filp_open() is of type struct file and don't forget to close it with filp_close() when you're done:

#include <linux/fs.h>
//other includes...

//other code...    

struct file *filp = filp_open("/dev/ttyS0");
//do serial stuff...
filp_close(filp);
Mike
  • 47,263
  • 29
  • 113
  • 177
  • @user1610075 - Did you include the right header file? (see edit above) – Mike Oct 31 '12 at 12:40
  • Ok now it works...anyway in the man it says something like it is not recommendend...moreover I found a reading example here http://www.howtoforge.com/reading-files-from-the-linux-kernel-space-module-driver-fedora-14 and seems pretty tricky to me, are you sure it is a good way to read from kernel space? – user1610075 Oct 31 '12 at 12:51
  • @user1610075 - it's not saying `filp_open` is not recommended, it's saying opening a file from the kernel is not recommended. But if you have to, this, or a mechanism based off of this, is the correct way (to the best of my knowledge). – Mike Oct 31 '12 at 13:14
  • Ah ok thanks! Listen I would need a non-blocking version of read, but I can't find any documentation...could you help me please? – user1610075 Oct 31 '12 at 18:26
  • That's kind of off topic, you should probably open a new question. But briefly, you could open with the `O_NONBLOCK` flag, or set this in `fcntl`, or use `select()` with `NULL` for timeouts – Mike Oct 31 '12 at 18:54
1

Finding your way around the kernel source can be pretty frightening since it's so large. Here's my favorite command: find . -iname "*.[chs]" -print0 | xargs -0 grep -i "<search term>.

A quick description:

  • find (obvious)
  • dot is the root directory of the kernel
  • iname is find the name ignoring case
  • .c .h and .s files contain code - look in them
  • print0 prints them out null terminated as they are found
  • xargs takes an input and uses it as an argument to another command (-0 is to use null terminated)
  • grep - search for string (ignoring case).

So for this search: "int open(" and you'll get some hits with tty in the name (those will be for consoles) - have a look at the code and see if they are what you want.

dave
  • 4,812
  • 4
  • 25
  • 38
  • You can do the same with grep solely: `grep -i -R --include="*.[chs]" "" .` – Nelson Oct 31 '12 at 12:08
  • I like my version better still because I can use it for things other than grep (perl expressions to replace found terms is a good example). But thanks for the tip (it can also be done with just find and --exec ... but xargs is faster) – dave Nov 01 '12 at 06:15
-2

Include the header file for open, usually #include <unistd.h>

Edit:

Not sure about kernel use, but do a man 2 open.

On my version of linux you might need all following:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

depending on the macros you are using.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • 1
    gives me "no existent"...maybe because I'm in a kernel module? – user1610075 Oct 31 '12 at 11:30
  • 1
    @user1610075 - Exactly. `unistd.h` is a part of `glibc`, that's not included in the kernel. The kernel has its own version of this `linux/unistd.h` – Mike Oct 31 '12 at 12:03