Linux workqueue question "Turn"

Source: Internet
Author: User
Tags joins

Transferred from: http://blog.csdn.net/angle_birds/article/details/9387365

Hello, you great God. I encountered a problem in the process of using Workqueue. The project adopts uclinux system, VoIP-related. There are two drivers, one is responsible for data transmission, and the other is responsible for making calls. Each of these two drives uses a workqueue. When the data transmission volume is very large, the workqueue responsible for data transmission is very resource-intensive and the CPU consumption can reach 60-70%. At this time, I call, that is, to call the Workqueue work, but at this time the call Workqueue execution will appear delay (this call workqueue is very sensitive to the timing), the phone is not normal. No data transfer or volume is very small, everything is OK. I try to put all the code in the interrupt program (so that no one can interrupt him, unless there is a higher level of interruption), but the phone calls the API will sleep, the kernel will crash (interrupt program can not sleep). I want to know now workqueue have the concept of priority? Some words I can set the Workqueue priority of the call to high. So no matter how busy the data transmission, the phone can always grab the CPU Ah! I checked the information on the Internet, Workqueue is actually a kernel thread, since it is a thread, there should be a priority concept AH. Since I do not have the experience of kernel programming, please also have the experience of the Warrior to give guidance! Thank you, little brother first! No trace of the peak blowing | level five
Workqueue is a kernel thread, but the task in the queue is not a thread. The interruption certainly does not have, the long time interruption certainly will collapse. You can flush workqueue to try. I don't quite know what you're doing.
Ask
Flush Workqueue has been tested, no. I flush the phone in the workqueue of the data transfer Workqueue, finally found that the phone or not immediately occupy the CPU. I understand that the use of workqueue words of the real-time process is not good, do not know if there is no other way? For example: Like Tasklet can be processed immediately, and can sleep like workqueue?
Reply
...... So what time do you want it to deal with sleep at once? How does the system know your needs ah, your exact tell the system AH
Comments | 0 2012-05-12 16:01 enthusiastic netizens

Why not use the thread to do, put the phone workqueue things in the interrupt thread, you can register with REQUEST_THREADED_IRQ

Ask
I'm using the uclinux,2.6.14 version, and I don't have this function yet. When was this function added? Request_threaded_irq

1. What is Workqueue
The workqueue mechanism in Linux is designed to simplify the creation of kernel threads. The kernel thread can be created by invoking the Workqueue interface. and the number of threads can be created based on the number of current system CPUs, so that threading transactions can be parallelized. Workqueue is a simple and effective mechanism in the kernel, and he clearly simplifies the creation of kernel daemon and facilitates user programming.

The Work queue (Workqueue) is another form of delaying work. The work queue can be pushed back into a kernel thread to execute, that is, the lower part can be executed in the context of the process. The most important thing is that the work queue is allowed to be re-dispatched or even asleep.

2. Data structure
We call the deferred task work, describing its data structure as work_struct:

[CPP]View Plaincopy
  1. struct Work_struct {
  2. atomic_long_t data; / * parameter of the work handler Func * /
  3. #define WORK_STRUCT_PENDING 0/* T If Work item PENDING execution */
  4. #define WORK_STRUCT_STATIC 1/* STATIC initializer (debugobjects) */
  5. #define WORK_STRUCT_FLAG_MASK (3UL)
  6. #define WORK_STRUCT_WQ_DATA_MASK (~work_struct_flag_mask)
  7. struct List_head entry; / * Pointer to the work of the connection * /
  8. work_func_t func; / * Work handler function * /
  9. #ifdef CONFIG_LOCKDEP
  10. struct Lockdep_map lockdep_map;
  11. #endif
  12. };

The work is organized into work queues (workqueue) with a structure of workqueue_struct:

[CPP]View Plaincopy
  1. struct Workqueue_struct {
  2. struct cpu_workqueue_struct *cpu_wq;
  3. struct List_head list;
  4. Const Char *name; /*workqueue name*/
  5. int singlethread; /* is not a single thread-single thread our preferred first CPU-0 is the default worker thread event*/
  6. int freezeable; / * Freeze threads during suspend * /
  7. int RT;
  8. };


In the case of multi-threading, Linux creates cpu_workqueue_struct based on the number of current system CPUs:

[CPP]View Plaincopy
    1. TRUCT CPU_WORKQUEUE_STRUCT {  
    2.   spinlock_t lock; /* because the worker thread needs to handle the work that is connected to it frequently, so the yoke protection is required */  
    3.  STRUCT LIST_HEAD WORKLIST;  
    4.  wait_queue_head_t more_work;  
    5.  struct work_struct *current_work;  /* current work*/  
    6.  struct workqueue_struct *wq;    /* workqueue*/   to which it belongs;
    7.  struct task_ Struct *thread; /* task context */  
    8. } ____cacheline_aligned;  

In this structure the main maintenance of a task queue, as well as kernel threads need to sleep waiting queue, in addition to maintain a task context, namely task_struct.
The relationship between the three is as follows:

3. Create a job
3.1 Creating a Work queue
A. Create_singlethread_workqueue (name)
As shown in the implementation mechanism of this function, the function returns a pointer variable of type struct workqueue_struct, where the memory address pointed to by the pointer variable is called KZALLOC dynamically generated inside the function. So driver is called when the work queue is no longer used:

void Destroy_workqueue (struct workqueue_struct *wq) to free the memory address here.

The CWQ in the figure is a PER-CPU type of address space. For Create_singlethread_workqueue, even for multi-CPU systems, the kernel is only responsible for creating a worker_thread kernel process. After the kernel process is created, the wait node in the diagram is defined first, then the worklist in the CWQ is checked in a loop body, and if the queue is empty, the wait node is added to More_work in Cwq and then dormant in the wait queue.

Driver calls Queue_work (struct workqueue_struct *wq, struct work_struct *work) to join the work node to the Wq. Work is added to the linked list that cwq->worklist points to. Queue_work joins a work node to the cwq->worklist and calls Wake_up to wake the Worker_thread process dormant on the cwq->more_work. WAKE_UP calls the Autoremove_wake_function function on the wait node and then removes the wait node from Cwq->more_work.

Worker_thread is dispatched again to begin processing all work nodes in the cwq->worklist ... When all the work nodes are processed, Worker_thread re-joins the wait node to Cwq->more_work and then sleeps again in the wait queue until driver calls Queue_work ...

B. Create_workqueue

In contrast to Create_singlethread_workqueue, Create_workqueue also assigns a WQ work queue, but the difference is that for a multi-CPU system, for each CPU, Will create a PER-CPU CWQ structure for it, and for each CWQ, a new worker_thread process will be generated. But when the work node is submitted to CWQ with Queue_work, which CPU calls the function, it adds the work node to the worklist on the CWQ corresponding to the CPU.

C. Summary
When the user calls Workqueue's initialization interface Create_workqueue or Create_singlethread_workqueue initializes the Workqueue queue, the kernel begins assigning a Workqueue object to the user. And chain it to a global workqueue queue. Linux then allocates a Cpu_workqueue_struct object with the same number of CPUs for the Workqueue object based on the current CPU, and each Cpu_workqueue_struct object has a task queue. Next, Linux allocates a kernel thread for each Cpu_workqueue_struct object, which is the kernel daemon to handle the tasks in each queue. At this point, the user invokes the initialization interface to complete the Workqueue initialization and returns the Workqueue pointer.

Once the workqueue is initialized, the context of the task run is built, but there is no executable task, so you need to define a specific Work_struct object. Then add the work_struct to the task queue, and Linux wakes up the daemon to handle the task.

The Workqueue kernel implementation principle described above can be described as follows:

3.2 Creating a Job
To use a work queue, the first thing to do is to create some work that needs to be pushed backwards. The structure can be statically built at compile time by Declare_work:
Declare_work (Name,void (*func) (void *), void *data);
This will statically create a work_struct structure named name, the function to execute is func, and the parameter is data.
Similarly, you can create a job with pointers at run time:
Init_work (Structwork_struct *work, Woid (*func) (void *), void *data);

4. Scheduling
A. Schedule_work

In most cases, it is not necessary to establish a work queue yourself, but to define work, to hook the work structure to the kernel's predefined event work queue, and to define a static global amount of work queue static struct Workqueue_ in kernel/workqueue.c struct *KEVENTD_WQ; The default worker thread is called events/n, where n is the number of the processor, and each processor corresponds to a thread. For example, a single-processor system only events/0 such a thread. The dual-processor system will have one more EVENTS/1 thread.
Schedule the work structure, add the work structure to the global event work queue Keventd_wq, and call the Queue_work generic module. The Keventd_wq interface is shielded from the outside, and the user does not need to know this parameter, which is equivalent to using default parameters. KEVENTD_WQ is maintained by the kernel itself, created, destroyed. The work will be dispatched immediately, and it will be executed once the worker thread on the processor on which it is located is awakened.

B. schedule_delayed_work (&work,delay);
Sometimes you don't want your work to be executed right away, but hopefully it will be executed after a delay. In this case, the timer can also be used to schedule the delay, after the expiration of the default timer callback function to register the work. After delaying delay, it is awakened by the timer and the work is added to the working queue Wq.

The work queue has no priority and is processed basically in a FIFO manner.

5. Example

[CPP]View Plaincopy
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/workqueue.h>
  4. Static struct workqueue_struct *queue=null;
  5. Static struct work_struct work;
  6. Staticvoid Work_handler (struct work_struct *data)
  7. {
  8. PRINTK (Kern_alert"work Handler function.\n");
  9. }
  10. static int __init test_init (void)
  11. {
  12. Queue=create_singlethread_workqueue ("Hello World"); /* Create a single-threaded work queue * /
  13. if (!queue)
  14. Goto Err;
  15. Init_work (&work,work_handler);
  16. Schedule_work (&work);
  17. Return0;
  18. Err:
  19. return-1;
  20. }
  21. static void __exit test_exit (void)
  22. {
  23. Destroy_workqueue (queue);
  24. }
  25. Module_license ("GPL");
  26. Module_init (Test_init);
  27. Module_exit (Test_exit);





































Serial number


interface functions


Description


1


Create_workqueue


Used to create a workqueue queue that creates a kernel thread for each CPU in the system. Input parameters:


@name: Name of Workqueue


2


Create_singlethread_workqueue


Used to create workqueue, creating only one kernel thread. Input parameters:


@name: Workqueue Name


3


Destroy_workqueue


Frees the Workqueue queue. Input parameters:


@ workqueue_struct: Workqueue queue pointer that needs to be freed


4


Schedule_work


The scheduler performs a specific task, and the tasks that are performed will be suspended into the WORKQUEUE--KEVENTD_WQ input parameters provided by the Linux system:


@ work_struct: Specific Task object pointer


5


Schedule_delayed_work


Delay a certain time to perform a specific task, functions similar to schedule_work, one more delay time, input parameters:


@work_struct: Specific Task object pointers


@delay: Delay Time


6


Queue_work


The schedule executes a task in a specified workqueue. Input parameters:


@ workqueue_struct: The specified workqueue pointer


@work_struct: Specific Task object pointers


7


Queue_delayed_work


Deferred scheduling performs a task in a specified workqueue, similar to queue_work, with one delay for input parameters.


Transferred from: http://bgutech.blog.163.com/blog/static/18261124320116181119889/

Linux workqueue question "Turn"

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.