INIT_WORK-Linux device drive Edition 3-7.6. Working queue

Source: Internet
Author: User
7.6. Work queue
Working queues are, on the surface, similar to taskets; they allow kernel code to request calls to a function at a certain time in the future. However, there are several significant differences between the two, including:

The result of tasklet running in the context of software interruption is that all tasklet code must be atomic. on the contrary, work queue functions run in a special kernel process context; as a result, they have more flexibility. in particular, the work queue function can sleep.

Tasklet often runs on the processor they are initially submitted. The work queue works in the same way, by default.

The kernel code can request the work queue function to be postponed for a specific interval.

The key difference between the two is that tasklet runs very quickly, in a short period of time, and in an atomic state, while a work queue function may have a high cycle but does not need to be atomic. Each mechanism has a suitable situation.

The work queue has a struct workqueue_struct type, in Define. A work queue must be explicitly created before use, using one of the following two functions:

Struct workqueue_struct * create_workqueue (const char * Name );
Struct workqueue_struct * create_singlethread_workqueue (const char * Name );

Each work queue has one or more dedicated processes ("kernel Threads") that run the functions submitted to this queue. if you use create_workqueue, you get a working queue that has a dedicated thread on each processor of the system. in many cases, all these threads are simple and excessive. If a single worker thread is sufficient, use create_singlethread_workqueue instead of creating a work queue.

To submit a task to a work queue, you need to fill in a work_struct structure. This can be completed at compilation, as shown below:

Declare_work (name, void (* function) (void *), void * data );

Here name is the declared structure name. function is the function called from the work queue, and data is the value passed to this function. if you need to create a work_struct structure at runtime, use the following two macro definitions:

Init_work (struct work_struct * Work, void (* function) (void *), void * data );
Prepare_work (struct work_struct * Work, void (* function) (void *), void * data );

Init_work performs more comprehensive initialization of the structure; you should use it when creating the structure for the first time. prepare_work performs almost the same job, but it is not initialized to connect the pointer from the work_struct structure to the work queue. if there is any possibility that this structure is currently submitted to a work queue, and you need to change this queue, use prepare_work instead of init_work.

There are two functions to submit work to a work queue:

Int queue_work (struct workqueue_struct * queue, struct work_struct * work );
Int queue_delayed_work (struct workqueue_struct * queue, struct work_struct * Work, unsigned long delay );

Each worker is added to the specified queue. if queue_delay_work is used, but the actual work is not performed until at least delay jiffies has passed. the return value from these functions is 0 if the work is successfully added to the queue. A non-zero result indicates that the work_struct structure has been waiting in the queue and has not been added for 2nd times.

In the future, this function will be called using the given data value. this function will run in the context of the worker thread, so it can be sleep if needed-although you should know how this sleep may affect other tasks submitted to the same work queue. what this function cannot do is, however, access the user space. because it runs in a kernel thread, there is no user space to access it.

To cancel a pending work queue entry, you can call:

Int cancel_delayed_work (struct work_struct * work );

The returned value is non-zero if this entry is canceled before it starts execution. the kernel ensures that the execution of the given entry is not initialized after cancel_delay_work is called. if cancel_delay_work returns 0, but this entry may already run on a different processor and may still run after cancel_delayed_work is called. make sure that the function does not run anywhere after cancel_delayed_work returns 0. You must follow this call to call it:

Void flush_workqueue (struct workqueue_struct * Queue );

After flush_workqueue is returned, the function submitted before this call is not executed anywhere in the system.

When you run out of a work queue, you can remove it and use:

Void destroy_workqueue (struct workqueue_struct * Queue );

7.6.1. Shared queue
A device driver does not need its own working queue in many cases. if you only submit tasks to the queue occasionally and simply use the shared tasks provided by the kernel, the default queue may be more effective. if you use this queue, but you must understand that you will share it with others. on the other hand, this means that you should not monopolize the queue for a long time (no long sleep), and it may take longer for them to turn to the processor.

The jiq ("just in queue") module outputs two files to demonstrate the use of the shared queue. They use a single work_struct structure, which is created as follows:

Static struct work_struct jiq_work;
/* This line is in jiq_init ()*/
Init_work (& jiq_work, jiq_print_wq, & jiq_data );

When a process reads/proc/jiqwq, this module initializes a series of routes through the shared working queue without delay.

Int schedule_work (struct work_struct * work );

Note that a different function is used when a shared queue is used; it only requires the work_struct structure as a parameter. The actual code in jiq looks like this:

Prepare_to_wait (& jiq_wait, & wait, task_interruptible );
Schedule_work (& jiq_work );
Schedule ();
Finish_wait (& jiq_wait, & wait );

The actual working function prints a line like the JIT module. Then, if necessary, re-submit the work_structcture to the working queue. Here is all jiq_print_wq:

Static void jiq_print_wq (void * PTR)
{
Struct clientdata * Data = (struct clientdata *) PTR;

If (! Jiq_print (PTR ))
Return;

If (data-> delay)
Schedule_delayed_work (& jiq_work, data-> delay );
Else
Schedule_work (& jiq_work );
}

If the user is reading the delayed device (/proc/jiqwqdelay), this function re-submits it in the delayed mode and uses schedule_delayed_work:

Int schedule_delayed_work (struct work_struct * Work, unsigned long delay );

If you look at the output from these two devices, it looks like:

% CAT/proc/jiqwq
Time Delta preempt pid cpu command
1113043 0 0 7 1 events/1
1113043 0 0 7 1 events/1
1113043 0 0 7 1 events/1
1113043 0 0 7 1 events/1
1113043 0 0 7 1 events/1
% CAT/proc/jiqwqdelay
Time Delta preempt pid cpu command
1122066 1 0 6 0 events/0

1122067 1 0 6 0 events/0
1122068 1 0 6 0 events/0
1122069 1 0 6 0 events/0
1122070 1 0 6 0 events/0

When/proc/jiqwq is read, there is no significant delay between printing of each row. conversely, when/proc/jiqwqdealy is read, there is a jiffy latency between each row. in each case, we can see that the same process name is printed; it is the name of the kernel thread that implements the shared queue. the CPU number is printed behind the slash. We never know which CPU will be running when the/proc file is read, but this function will always run on the same processor.

If you need to cancel a work entry that has been submitted to the work queue, you can use cancel_delayed_work, as described above. refreshing the shared queue requires a different function,:

Void flush_scheduled_work (void );

Because you don't know who else may use this queue, you never really know how long it may take to return flush_schduled_work.

--------------------------------------------------------------------------------

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.