Skip to main content

2.3 Questions

Alright, close the books — the theory is over. Now it's time to get our hands dirty.

We've covered a lot of ground in this chapter: from procfs to sysfs, then debugfs, netlink sockets, and finally ioctl. If you don't write the code yourself, these mechanisms will remain dry concepts on a page. To truly cement this knowledge, you need to apply it to real problems.

The exercises below aren't fill-in-the-blank questions — they're genuine engineering tasks. If you can complete them independently, even if it takes some time to look things up, you've officially crossed the threshold into this field.

Don't worry — reference code for some exercises is available in this book's GitHub repository, but I strongly recommend trying to write them yourself first. As Donald Knuth said, "The best test is when you have to explain it." Here, the best test is when you have to implement it.


Exercise 2.1 — sysfs_on_misc ⭐⭐

Task: Go back to the simple misc device driver we wrote in Chapter 1. Dig it up — we're going to extend it.

Requirements:

  1. Extend this driver by creating two attribute files under sysfs.
  2. You need to implement the corresponding show and store callback functions.
  3. Read from and write to these files from userspace (via shell or a C program) to verify the interface works correctly.

Tip: Remember the DEVICE_ATTR macro? It will save you a lot of work. Don't forget to attach it during initialization with device_create_file and detach it during cleanup with device_remove_file.


Exercise 2.2 — sysfs_addrxlate ⭐⭐⭐

This is an advanced exercise that touches on deep memory management mechanisms.

Task: Write a simple platform driver that leverages Linux kernel memory management knowledge to implement an "address translation" feature.

Requirements:

  1. Create two sysfs files: addrxlate_kva2pa and addrxlate_pa2kva.
  2. addrxlate_kva2pa:
    • The user writes a kernel virtual address to the file.
    • The driver converts it to the corresponding physical address.
    • When the user reads the file, it displays the translated physical address.
  3. addrxlate_pa2kva:
    • The reverse operation: write a physical address, and read back the kernel virtual address.

Tip: You'll need to consult the kernel documentation to understand how to work with macros like virt_to_phys and related page table operations. This exercise will help you understand the mapping relationship between kernel space and physical memory.


Exercise 2.3 — dbgfs_disp_pgoff ⭐⭐

Task: Write a kernel module that exposes kernel configuration parameters through debugfs.

Requirements:

  1. Create a file named dbgfs_disp_pgoff under the debugfs mount point.
  2. When the user reads this file, the driver returns the value of the current kernel's PAGE_OFFSET macro.

Tip: PAGE_OFFSET is a key marker for the kernel space starting address. This exercise will familiarize you with debugfs APIs (such as debugfs_create_file) and how to handle simple read requests.


Exercise 2.4 — dbgfs_showall_threads ⭐⭐⭐

Task: Write a kernel module that uses debugfs to provide a real-time view of system processes.

Requirements:

  1. Create a file dbgfs_showall_threads under debugfs (note: you may need to create a subdirectory).
  2. When the user reads this file, the driver iterates through all tasks in the system (task_struct) and outputs key information for each thread in CSV format.

Suggested output fields: TGID,PID,current,stack-start,name,#threads

  • Pay attention to the [name] format for kernel threads.
  • #threads should only display a positive integer for multi-threaded processes; do not output it for single-threaded processes.

Tip: This requires using the for_each_process macro or a similar iteration mechanism. Also, be mindful of concurrency issues — don't let the scheduler block you while reading. This exercise will give you a feel for debugfs's flexibility compared to procfs — there are far fewer formatting constraints.


Exercise 2.5 — ioctl assignment #1 ⭐⭐

Task: Based on the provided ch2/ioctl_intf/ template code, implement the classic userspace-to-kernel interaction via ioctl.

Requirements:

  1. Write a userspace C program and a kernel character device driver.
  2. Implement the unlocked_ioctl method in the driver.
  3. Add a new ioctl command: IOCTL_LLKD_IOCQPGOFF.
  4. When the userspace program queries via this command, the kernel returns the value of PAGE_OFFSET to userspace.

Tip: Don't forget the definition of the _IOR macro — it's essential for defining ioctl command numbers.


Exercise 2.6 — ioctl_undoc ⭐⭐⭐

Task: Let's do something "dangerous" — implement an undocumented ioctl command to retrieve the driver's internal state.

Requirements:

  1. Again, based on the ch2/ioctl_intf/ template.
  2. Define a "driver context data structure" in the driver (the struct we used in earlier examples), containing a few fields such as statistics and status flags. Allocate and initialize it during module initialization.
  3. Add a fourth ioctl command: IOCTL_LLKD_IOCQDRVSTAT.
  4. Key point: This command is "undocumented," meaning it bypasses the常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规常规