Reputation: 13
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
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
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 :
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.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 :
struct work_struct
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);
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