Showing posts with label Kernel. Show all posts
Showing posts with label Kernel. Show all posts

Sunday, August 15, 2010

Process holding the block devices

Recently I had to write a program to shred a live disk. This was a security requirement for our devices. However, while testing the program, I found that this always failed. It was possible to overwrite whole of the disk except for a single sector. I knew that some process is using this part of the disk and that is the reason I was not able to write to it. I did an lsof for the device when the write operation was going on. There were certain process having files opened from that device. However, even after killing them, my program was not successful in writing the entire disk. Later, I even figured out that the programs with open files were not causing any real problem! But, then what was blocking the overwrite?

Now, we have decided to reboot the machine and do this operation before boot up. However, my doubt stayed till today. It is only today that I came to know about the real culprit. It is none other than the kernel. When a FS is mounted, the disk is opened by kernel. As long as it is mounted, kernel holds this open fd. As mount would have exited long back, so, one will never see this being caused by mount!

Monday, March 8, 2010

Kernel Thread

This post is on how to create a simple kernel thread. Note that the idea here is to explain the kthread and hence not much importance is given to other aspects.


kthread.c




#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kthread.h>

struct task_struct *ts;

int my_thread(void *data)
{


    printk("%s\n",data);<
    while(1)
    {
        printk("I am a kernel thread\n");
        msleep(3000);
        if(kthread_should_stop()) return 0;
    }
    return -1;
}

int tinit(void)
{
    ts=kthread_run(my_thread,"message from init","MyKernelThread");
    return 0;
}

void tstop(void)
{

    kthread_stop(ts);
}

module_init(tinit);
module_exit(tstop);



Makefile



obj-m := kthread.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=`pwd` modules


clean:
    @rm -f *.ko *.o *.mod.o *.mod.c



How does it work?

It is very simple. The function kthread_run is not actually a function. It is a macro defined in include/linux/kthread.h. This macro takes care of creating and starting the kernel thread. my_thread is the function that will be run by this thread. All these are very similar to user land threads. However, there is a notable difference here. From the thread function you should keep checking if your thread is being stopped and return. This is done by calling kthread_should_stop(). If this function returns true, that means it is time for us to return. This is a nice feature as this will allow us to do some cleanup before we exit. (This is a must since, if this function does not return, your rmmod will hang). As you can see, the thread is stopped by kthread_stop call. So, what are you waiting for? Have some fun with your brand new kernel thread

Wednesday, August 13, 2008

Training for Ankit (3)

The zap driver:

1. Used wcfxo.c as the datum

2. Created the following dummy functions
wcfxo_open
wcfxo_close
wcfxo_read
wcfxo_write
wcfxo_hooksig

3. Made the hello_spaninit function to initialize the span

4. Made the zaptel settings as I have shown in the first post in this series

5. Start zaptel service

6. Build and insert module

7. Run ztcfg

8. On the console, dial 1000

9. tail -f /var/log/messages should show message from hooksig

10. On the console, hangup

11. tail -f /var/log/messages should show message from hooksig

12. Since syslog buffers the message and does stuff like "Last message repeated X times" you might not see the second message immediately

#include
#include
#include "zaptel.h"

MODULE_LICENSE("GPL");

extern int gpltest;

struct hpvt {
int pos;
struct zt_span span;
struct zt_chan chan;
char variety[128];
}hello;

static int hello_spanInit();

static int hello_init(void)
{
printk(KERN_ALERT "Before: Hello, world %d \n",gpltest);
hello_spanInit();
printk(KERN_ALERT "After: Hello, world\n");
return 0;
}

static void hello_exit(void)
{
printk(KERN_ALERT "Before: Goodbye, cruel world\n");
zt_unregister(&hello.span);
printk(KERN_ALERT "After: Goodbye, cruel world\n");
}

static int wcfxo_open(struct zt_chan *c)
{

printk(KERN_ALERT "Open called\n");
return 0;
}

static int wcfxo_close(struct zt_chan *c)
{

printk(KERN_ALERT "Close called\n");
return 0;
}

static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
{

printk(KERN_ALERT "Hooksig called\n");
return 0;

}

static int wcfxo_watchdog(struct zt_span *span, int event)
{
printk("FXO: Restarting DMA\n");
return 0;
}


static int hello_spanInit()
{
struct hpvt *wc=&hello;

strcpy(hello.variety,"Thinvent");
hello.pos=0;
/* Zapata stuff */
sprintf(hello.span.name, "SARIN/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
sprintf(wc->chan.name, "SARIN/%d/%d", wc->pos, 0);
snprintf(wc->span.location, sizeof(wc->span.location) - 1,"HERE!");
wc->span.manufacturer = "SARIN";
strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1);
wc->chan.sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF;
wc->chan.chanpos = 1;
wc->span.chans = &wc->chan;
wc->span.channels = 1;
wc->span.hooksig = wcfxo_hooksig;
// wc->span.irq = wc->dev->irq;
wc->span.open = wcfxo_open;
wc->span.close = wcfxo_close;
wc->span.flags = ZT_FLAG_RBS;
wc->span.deflaw = ZT_LAW_MULAW;
wc->span.watchdog = wcfxo_watchdog;
#ifdef ENABLE_TASKLETS
tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc);
#endif
init_waitqueue_head(&wc->span.maintq);

wc->span.pvt = wc;
wc->chan.pvt = wc;
if (zt_register(&wc->span, 0)) {
printk("Unable to register span with zaptel\n");
return -1;
}
return 0;

}

module_init(hello_init);
module_exit(hello_exit);

Make file

obj-m += tzap.o
EXTRA_CFLAGS += -I/root/zaptel/kernel

all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

Tuesday, August 12, 2008

Training for Ankit (2)

Ok, we built the kernel module. What do we do with it now?

1. Insert the kernel module to kernel
insmod tzap.ko

2. See the messages appearing in /var/log/messages

At this point, Ankit asked me why tail /var/log/messages? Why can't we see that directly?
Ans: Insmod calls the hello_init function. The message comes from

printk(KERN_ALERT "Before: Hello, world %d \n",gpltest);

Now, KERN_ALERT is a priority for kernel messages. ALERT is not a high priority so that the message comes on our Terminal. We changed the line to

printk(KERN_EMERG "Before: Hello, world %d \n",gpltest);

This time, the message appeared on the Terminal. I then showed him /etc/syslog.conf and told him that, it is syslog which reads these messages and decides what to do with it. I showed him my /etc/syslog.conf and explained how various messages are destined to go to various locations.

3. Unloading the module

This is done with the command rmmod tzap. hello_exit is called when this happens.

4. Module license line.

MODULE_LICENSE("GPL"); or something like that tells the module is licensed under GPL license. This has an important for our customer. They will have to GPL the code if they plan to access the symbols that are exported using EXPORT_SYMBOL_GPL. Anyway, they are lucky and zaptel does not have GPL exports.

5. Init & Exit

module_init and module_exit defines the entry points for insmod and rmmod.

6. One more step __init and __exit

These macros tell the kernel that the functions thus defined are specific to module loading and unloading. I told him to remember the Linux boot process and the line "Freeing unused kernel memory". This is possible because if I mark a function as __init, the kernel knows it has no need of the function after initialization. This allows the kernel to free some memory after boot-up

Training for Ankit (1)

Today I was at customers development centre. Ankit is to develop the driver for the hardware they develop. This post will record the session that I had with Ankit.

Ankit was new to kernel programming. Even I have not mastered this beast well. Neverthless, I got Ankit started with it.

1. Zaptel discussion

It is not necessary to define a span in case of an FXS/FXO. Just need to define a channel.
However, for registering fxs/fxo also, we pass a span argument to zaptel. I asked Ankit to look at span as an abstraction for a device (E1 card, FXS etc) which 'n' channels. (n = 1, for FXS)
I showed him how to define a fxo channel.
zaptel.conf
loadzone = us
defaultzone = us
fxsks=1
zapata.conf (Additions only)
signalling=fxs_ks
callerid="Green Phone"<(256) 428-6121>
channel => 1
extensions.conf additions
exten => 1000,1,Dial(Zap/1)

2. Kernel module programming

To program kernel modules, you need to have kernel source for your current kernel.
I asked him to first download LDD3.
Then, we copied the code from second chapter and compiled the module.
This had to be done on my laptop, as he did not have kernel sources installed on his system.

#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);

Then we created the makefile

obj-m += tzap.o
EXTRA_CFLAGS += -I/root/zaptel/kernel

all:
make -C /lib/modules/$(shell uname -r)/build M=`pwd` modules

With the make file in place, we compiled the module and inserted it.


  1. obj-m is a variable understood by kernel build system
  2. obj-m = tzap.o indicates that the name of your module source file is tzap.c
  3. EXTRA_CFLAGS defines the extra compile time flags specific for your module
  4. In this case that extra flag is not really necessary. But as we do more work with this driver, we will need it.
  5. Make command arguments: -C Tells the make to change to before actually running
  6. Make command arguments: M=`pwd`defines M, which will be used by kernel build system to determine the directory in which module source is present
  7. Make command arguments: modules is the target to build
We invoke the kernel build system which in turn compiles the module for us.