vk_pk
vk_pk

Reputation: 13

Linux kernel programming on threads for kernel version 3.x

I would like to know where can I find good tutorial or examples for linux kernel programming on threading for kernel 3.x?

Any help would be appreciated.....

Upvotes: 1

Views: 1166

Answers (1)

Rerito
Rerito

Reputation: 6086

I would recommend you to dig on several ways of deferring work in the Kernel (because it is what you need in the end).

The solution which is the closest of what you explicitly asked is to use

struct task_struct * kthread_create(int (*threadfn) (void *data), void * data, const char namefmt[], ...);

An other possible way that may fit your problem is the use of work queues. With this, you have to first declare a work you want to defer. You can do this with two preprocessor macros depending on where you want your work structure allocated :

  • On the stack : DECLARE_WORK(name, void (*func)(void*), void *data); will automatically initialize a struct work_struct on the stack with the func worker function that will be fed with data when run.
  • On the heap : suppose you have already allocated a struct work_struct object and you just want to initialize it with your function and the suitable data. Then you should use INIT_WORK(struct work_struct *work, void (*func)(void*), void *data);

When you want your task to be run, you have to schedule it, it will then appear on the list of works to run in the worker thread of the related work queue. If you just want to use the default work queue, you'll have to use one of the two functions below :

int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);

delay is expressed in jiffies (ticks of your processor clock).

If you have created a custom work queue, you'll have to use other functions. But first, let's see how you can create your own work queue object. To achieve this, you'll only have to call :

struct workqueue_struct create_workqueue(const char *name);

Once done, you can add pending work to the queue using function similar to the two displayed before.

int queue_work(struct workqueue_struct *wq, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *wq,
    struct work_struct *work, unsigned long delay);

If you want the pending works list to be flushed, just use :

/* On the default work queue */
void flush_scheduled_work(void);

/* On a dynamically created work queue */
void flush_workqueue(struct workqueue_struct *wq);

Note that this will note flush delayed work that are not yet ready to go ... If you want to cancel delayed work you'll have to use int cancel_delayed_work(struct work_struct *work);. The worker thread acts as follows :

  1. While the list of works to run is non-empty :
    1. It grabs the work at the head of the list (struct work_struct object).
    2. It runs the object func fed with the object data, if the work struct is stored in struct work_struct *work it will perform (*work->func)(work->data);
  2. If the scheduled works list is empty, it goes to sleep. It will be woken up when you then schedule work.

Obviously, this second option is not suitable when you need to have a background task always ready to run. In this case, a standard kthread is what you need. See the manual page I linked, it explains how to use it quite clearly.

To answer your problem, you can have two threads running. A sender and a receiver. The receiver is fed with incoming packets (this can be more complicated than it seems, you may have to deal with irq handlers to do so ...). Thus, the kthread_create option is good for you. On the other hand, you could have a bottom half that would be scheduled and run ONCE when you get data to send (for the sender) or just received an appropriate packet (the receiver). In this case, you may have to use work queues and tasklets (or softirqs). I'll edit my post later to describe these beasts since I am currently running out of time.

Upvotes: 1

Related Questions