mirror of
https://github.com/sysprog21/lkmpg.git
synced 2025-04-22 20:53:23 +08:00
deploy: cd2ba2447db846de67fd5c4a6a33c50dd823d96e
This commit is contained in:
parent
d1cf11f396
commit
2ee7087528
125
index.html
125
index.html
@ -4769,9 +4769,10 @@ better suited to running multiple things in a sequence.
|
||||
<h4 class='subsectionHead' id='tasklets'><span class='titlemark'>14.1 </span> <a id='x1-5400014.1'></a>Tasklets</h4>
|
||||
<!-- l. 1765 --><p class='noindent'>Here is an example tasklet module. The
|
||||
<code> <span class='ectt-1000'>tasklet_fn</span>
|
||||
</code> function runs for a few seconds and in the mean time execution of the
|
||||
</code> function runs for a few seconds. In the meantime, execution of the
|
||||
<code> <span class='ectt-1000'>example_tasklet_init</span>
|
||||
</code> function continues to the exit point.
|
||||
</code> function may continue to the exit point, depending on whether it is interrupted by
|
||||
<span class='ecbx-1000'>softirq</span>.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb77'><a id='x1-54004r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2403'><span class='ectt-0800'>/*</span></span>
|
||||
@ -4818,7 +4819,7 @@ better suited to running multiple things in a sequence.
|
||||
<a id='x1-54086r42'></a><span class='ecrm-0500'>42</span>
|
||||
<a id='x1-54088r43'></a><span class='ecrm-0500'>43</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2447'><span class='ectt-0800'>"Tasklet example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-54090r44'></a><span class='ecrm-0500'>44</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2448'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1770 --><p class='indent'> So with this example loaded <code> <span class='ectt-1000'>dmesg</span>
|
||||
<!-- l. 1771 --><p class='indent'> So with this example loaded <code> <span class='ectt-1000'>dmesg</span>
|
||||
</code> should show:
|
||||
|
||||
|
||||
@ -4830,23 +4831,23 @@ Example tasklet starts
|
||||
Example tasklet init continues...
|
||||
Example tasklet ends
|
||||
</pre>
|
||||
<!-- l. 1777 --><p class='nopar'>Although tasklet is easy to use, it comes with several defators, and developers are
|
||||
<!-- l. 1778 --><p class='nopar'>Although tasklet is easy to use, it comes with several defators, and developers are
|
||||
discussing about getting rid of tasklet in linux kernel. The tasklet callback
|
||||
runs in atomic context, inside a software interrupt, meaning that it cannot
|
||||
sleep or access user-space data, so not all work can be done in a tasklet
|
||||
handler. Also, the kernel only allows one instance of any given tasklet to be
|
||||
running at any given time; multiple different tasklet callbacks can run in
|
||||
parallel.
|
||||
</p><!-- l. 1782 --><p class='indent'> In recent kernels, tasklets can be replaced by workqueues, timers, or threaded
|
||||
</p><!-- l. 1783 --><p class='indent'> In recent kernels, tasklets can be replaced by workqueues, timers, or threaded
|
||||
interrupts.<span class='footnote-mark'><a href='#fn1x0' id='fn1x0-bk'><sup class='textsuperscript'>1</sup></a></span><a id='x1-54092f1'></a>
|
||||
While the removal of tasklets remains a longer-term goal, the current kernel contains more
|
||||
than a hundred uses of tasklets. Now developers are proceeding with the API changes and
|
||||
the macro <code> <span class='ectt-1000'>DECLARE_TASKLET_OLD</span>
|
||||
</code> exists for compatibility. For further information, see <a class='url' href='https://lwn.net/Articles/830964/'><span class='ectt-1000'>https://lwn.net/Articles/830964/</span></a>.
|
||||
</p><!-- l. 1788 --><p class='noindent'>
|
||||
</p><!-- l. 1789 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='work-queues'><span class='titlemark'>14.2 </span> <a id='x1-5500014.2'></a>Work queues</h4>
|
||||
<!-- l. 1790 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
<!-- l. 1791 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4883,36 +4884,36 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
<a id='x1-55062r31'></a><span class='ecrm-0500'>31</span>
|
||||
<a id='x1-55064r32'></a><span class='ecrm-0500'>32</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2476'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-55066r33'></a><span class='ecrm-0500'>33</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2477'><span class='ectt-0800'>"Workqueue example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1795 --><p class='noindent'>
|
||||
<!-- l. 1796 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='interrupt-handlers'><span class='titlemark'>15 </span> <a id='x1-5600015'></a>Interrupt Handlers</h3>
|
||||
<!-- l. 1797 --><p class='noindent'>
|
||||
<!-- l. 1798 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4 class='subsectionHead' id='interrupt-handlers1'><span class='titlemark'>15.1 </span> <a id='x1-5700015.1'></a>Interrupt Handlers</h4>
|
||||
<!-- l. 1799 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we have done as a
|
||||
<!-- l. 1800 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we have done as a
|
||||
response to a process asking for it, either by dealing with a special file, sending an
|
||||
<code> <span class='ectt-1000'>ioctl()</span>
|
||||
</code>, or issuing a system call. But the job of the kernel is not just to respond to process
|
||||
requests. Another job, which is every bit as important, is to speak to the hardware
|
||||
connected to the machine.
|
||||
</p><!-- l. 1803 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
</p><!-- l. 1804 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
computer’s hardware. The first type is when the CPU gives orders to the hardware,
|
||||
the order is when the hardware needs to tell the CPU something. The second, called
|
||||
interrupts, is much harder to implement because it has to be dealt with when
|
||||
convenient for the hardware, not the CPU. Hardware devices typically have a very
|
||||
small amount of RAM, and if you do not read their information when available, it is
|
||||
lost.
|
||||
</p><!-- l. 1808 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
</p><!-- l. 1809 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
are two types of IRQ’s, short and long. A short IRQ is one which is expected to take
|
||||
a very short period of time, during which the rest of the machine will be blocked and
|
||||
no other interrupts will be handled. A long IRQ is one which can take longer, and
|
||||
during which other interrupts may occur (but not interrupts from the same
|
||||
device). If at all possible, it is better to declare an interrupt handler to be
|
||||
long.
|
||||
</p><!-- l. 1814 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it is doing (unless it is
|
||||
</p><!-- l. 1815 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it is doing (unless it is
|
||||
processing a more important interrupt, in which case it will deal with this one only
|
||||
when the more important one is done), saves certain parameters on the stack and
|
||||
calls the interrupt handler. This means that certain things are not allowed in the
|
||||
@ -4924,10 +4925,10 @@ heavy work deferred from an interrupt handler. Historically, BH (Linux
|
||||
naming for <span class='ecti-1000'>Bottom Halves</span>) statistically book-keeps the deferred functions.
|
||||
<span class='ecbx-1000'>Softirq </span>and its higher level abstraction, <span class='ecbx-1000'>Tasklet</span>, replace BH since Linux
|
||||
2.3.
|
||||
</p><!-- l. 1824 --><p class='indent'> The way to implement this is to call
|
||||
</p><!-- l. 1825 --><p class='indent'> The way to implement this is to call
|
||||
<code> <span class='ectt-1000'>request_irq()</span>
|
||||
</code> to get your interrupt handler called when the relevant IRQ is received.
|
||||
</p><!-- l. 1826 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
</p><!-- l. 1827 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
designed in a way that chains two interrupt controllers, so that all the IRQs
|
||||
from interrupt controller B are cascaded to a certain IRQ from interrupt
|
||||
controller A. Of course, that requires that the kernel finds out which IRQ it
|
||||
@ -4944,7 +4945,7 @@ need to solve another truckload of problems. It is not enough to know if a
|
||||
certain IRQs has happened, it’s also important to know what CPU(s) it was
|
||||
for. People still interested in more details, might want to refer to "APIC"
|
||||
now.
|
||||
</p><!-- l. 1835 --><p class='indent'> This function receives the IRQ number, the name of the function,
|
||||
</p><!-- l. 1836 --><p class='indent'> This function receives the IRQ number, the name of the function,
|
||||
flags, a name for <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/proc/interrupts</span></span></span> and a parameter to be passed to the
|
||||
interrupt handler. Usually there is a certain number of IRQs available.
|
||||
How many IRQs there are is hardware-dependent. The flags can include
|
||||
@ -4954,16 +4955,16 @@ How many IRQs there are is hardware-dependent. The flags can include
|
||||
<code> <span class='ectt-1000'>SA_INTERRUPT</span>
|
||||
</code> to indicate this is a fast interrupt. This function will only succeed if there is not
|
||||
already a handler on this IRQ, or if you are both willing to share.
|
||||
</p><!-- l. 1841 --><p class='noindent'>
|
||||
</p><!-- l. 1842 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='detecting-button-presses'><span class='titlemark'>15.2 </span> <a id='x1-5800015.2'></a>Detecting button presses</h4>
|
||||
<!-- l. 1843 --><p class='noindent'>Many popular single board computers, such as Raspberry Pi or Beagleboards, have a
|
||||
<!-- l. 1844 --><p class='noindent'>Many popular single board computers, such as Raspberry Pi or Beagleboards, have a
|
||||
bunch of GPIO pins. Attaching buttons to those and then having a button press do
|
||||
something is a classic case in which you might need to use interrupts, so that instead
|
||||
of having the CPU waste time and battery power polling for a change in input state,
|
||||
it is better for the input to trigger the CPU to then run a particular handling
|
||||
function.
|
||||
</p><!-- l. 1847 --><p class='indent'> Here is an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
</p><!-- l. 1848 --><p class='indent'> Here is an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
an LED is connected to GPIO 4. You can change those numbers to whatever is
|
||||
appropriate for your board.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -5112,14 +5113,14 @@ appropriate for your board.
|
||||
<a id='x1-58284r142'></a><span class='ecrm-0500'>142</span>
|
||||
<a id='x1-58286r143'></a><span class='ecrm-0500'>143</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2584'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-58288r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2585'><span class='ectt-0800'>"Handle some GPIO interrupts"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1852 --><p class='noindent'>
|
||||
<!-- l. 1853 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='bottom-half'><span class='titlemark'>15.3 </span> <a id='x1-5900015.3'></a>Bottom Half</h4>
|
||||
<!-- l. 1854 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
<!-- l. 1855 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
way to do that without rendering the interrupt unavailable for a significant duration
|
||||
is to combine it with a tasklet. This pushes the bulk of the work off into the
|
||||
scheduler.
|
||||
</p><!-- l. 1858 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
</p><!-- l. 1859 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
when an interrupt is triggered.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -5293,19 +5294,19 @@ when an interrupt is triggered.
|
||||
<a id='x1-59330r165'></a><span class='ecrm-0500'>165</span>
|
||||
<a id='x1-59332r166'></a><span class='ecrm-0500'>166</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2713'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-59334r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2714'><span class='ectt-0800'>"Interrupt with top and bottom half"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1862 --><p class='noindent'>
|
||||
<!-- l. 1863 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='crypto'><span class='titlemark'>16 </span> <a id='x1-6000016'></a>Crypto</h3>
|
||||
<!-- l. 1864 --><p class='noindent'>At the dawn of the internet, everybody trusted everybody completely…but that did
|
||||
<!-- l. 1865 --><p class='noindent'>At the dawn of the internet, everybody trusted everybody completely…but that did
|
||||
not work out so well. When this guide was originally written, it was a more innocent
|
||||
era in which almost nobody actually gave a damn about crypto - least of all kernel
|
||||
developers. That is certainly no longer the case now. To handle crypto stuff, the
|
||||
kernel has its own API enabling common methods of encryption, decryption and your
|
||||
favourite hash functions.
|
||||
</p><!-- l. 1869 --><p class='noindent'>
|
||||
</p><!-- l. 1870 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='hash-functions'><span class='titlemark'>16.1 </span> <a id='x1-6100016.1'></a>Hash functions</h4>
|
||||
<!-- l. 1872 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
<!-- l. 1873 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5373,20 +5374,20 @@ demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
<a id='x1-61124r62'></a><span class='ecrm-0500'>62</span>
|
||||
<a id='x1-61126r63'></a><span class='ecrm-0500'>63</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2766'><span class='ectt-0800'>"sha256 hash test"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-61128r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2767'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1877 --><p class='indent'> Install the module:
|
||||
<!-- l. 1878 --><p class='indent'> Install the module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb82'><a id='x1-61132r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo insmod cryptosha256.ko</span>
|
||||
<a id='x1-61134r2'></a><span class='ecrm-0500'>2</span><span class='ectt-1000'>sudo dmesg</span></pre>
|
||||
<!-- l. 1884 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1886 --><p class='indent'> Finally, remove the test module:
|
||||
<!-- l. 1885 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1887 --><p class='indent'> Finally, remove the test module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb83'><a id='x1-61137r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo rmmod cryptosha256</span></pre>
|
||||
<!-- l. 1892 --><p class='noindent'>
|
||||
<!-- l. 1893 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='symmetric-key-encryption'><span class='titlemark'>16.2 </span> <a id='x1-6200016.2'></a>Symmetric key encryption</h4>
|
||||
<!-- l. 1894 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
<!-- l. 1895 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
and a password.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -5591,10 +5592,10 @@ and a password.
|
||||
<a id='x1-62392r196'></a><span class='ecrm-0500'>196</span>
|
||||
<a id='x1-62394r197'></a><span class='ecrm-0500'>197</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2919'><span class='ectt-0800'>"Symmetric key encryption example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-62396r198'></a><span class='ecrm-0500'>198</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2920'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1898 --><p class='noindent'>
|
||||
<!-- l. 1899 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='virtual-input-device-driver'><span class='titlemark'>17 </span> <a id='x1-6300017'></a>Virtual Input Device Driver</h3>
|
||||
<!-- l. 1900 --><p class='noindent'>The input device driver is a module that provides a way to communicate
|
||||
<!-- l. 1901 --><p class='noindent'>The input device driver is a module that provides a way to communicate
|
||||
with the interaction device via the event. For example, the keyboard
|
||||
can send the press or release event to tell the kernel what we want to
|
||||
do. The input device driver will allocate a new input structure with
|
||||
@ -5602,7 +5603,7 @@ do. The input device driver will allocate a new input structure with
|
||||
</code> and sets up input bitfields, device id, version, etc. After that, registers it by calling
|
||||
<code> <span class='ectt-1000'>input_register_device()</span>
|
||||
</code>.
|
||||
</p><!-- l. 1905 --><p class='indent'> Here is an example, vinput, It is an API to allow easy
|
||||
</p><!-- l. 1906 --><p class='indent'> Here is an example, vinput, It is an API to allow easy
|
||||
development of virtual input drivers. The drivers needs to export a
|
||||
<code> <span class='ectt-1000'>vinput_device()</span>
|
||||
</code> that contains the virtual device name and
|
||||
@ -5618,7 +5619,7 @@ development of virtual input drivers. The drivers needs to export a
|
||||
</li>
|
||||
<li class='itemize'>the readback function: <code> <span class='ectt-1000'>read()</span>
|
||||
</code></li></ul>
|
||||
<!-- l. 1915 --><p class='indent'> Then using <code> <span class='ectt-1000'>vinput_register_device()</span>
|
||||
<!-- l. 1916 --><p class='indent'> Then using <code> <span class='ectt-1000'>vinput_register_device()</span>
|
||||
</code> and <code> <span class='ectt-1000'>vinput_unregister_device()</span>
|
||||
</code> will add a new device to the list of support virtual input devices.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -5627,7 +5628,7 @@ development of virtual input drivers. The drivers needs to export a
|
||||
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb85'><a id='x1-63012r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2921'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> init(</span><span id='textcolor2922'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *);</span></pre>
|
||||
<!-- l. 1921 --><p class='indent'> This function is passed a <code> <span id='textcolor2923'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> vinput</span>
|
||||
<!-- l. 1922 --><p class='indent'> This function is passed a <code> <span id='textcolor2923'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> vinput</span>
|
||||
</code> already initialized with an allocated <code> <span id='textcolor2924'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> input_dev</span>
|
||||
</code>. The <code> <span class='ectt-1000'>init()</span>
|
||||
</code> function is responsible for initializing the capabilities of the input device and register
|
||||
@ -5635,20 +5636,20 @@ it.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb86'><a id='x1-63018r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2925'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> send(</span><span id='textcolor2926'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *, </span><span id='textcolor2927'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *, </span><span id='textcolor2928'><span class='ectt-0800'>int</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1928 --><p class='indent'> This function will receive a user string to interpret and inject the event using the
|
||||
<!-- l. 1929 --><p class='indent'> This function will receive a user string to interpret and inject the event using the
|
||||
<code> <span class='ectt-1000'>input_report_XXXX</span>
|
||||
</code> or <code> <span class='ectt-1000'>input_event</span>
|
||||
</code> call. The string is already copied from user.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb87'><a id='x1-63023r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2929'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> read(</span><span id='textcolor2930'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *, </span><span id='textcolor2931'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *, </span><span id='textcolor2932'><span class='ectt-0800'>int</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1935 --><p class='indent'> This function is used for debugging and should fill the buffer parameter with the
|
||||
<!-- l. 1936 --><p class='indent'> This function is used for debugging and should fill the buffer parameter with the
|
||||
last event sent in the virtual input device format. The buffer will then be copied to
|
||||
user.
|
||||
</p><!-- l. 1938 --><p class='indent'> vinput devices are created and destroyed using sysfs. And, event injection is done
|
||||
</p><!-- l. 1939 --><p class='indent'> vinput devices are created and destroyed using sysfs. And, event injection is done
|
||||
through a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node. The device name will be used by the userland to export a new
|
||||
virtual input device.
|
||||
</p><!-- l. 1942 --><p class='indent'> The <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</p><!-- l. 1943 --><p class='indent'> The <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> structure is similar to other attribute types we talked about in section <a href='#sysfs-interacting-with-your-module'>8<!-- tex4ht:ref: sec:sysfs --></a>:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5659,7 +5660,7 @@ virtual input device.
|
||||
<a id='x1-63041r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor2939'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> (*store)(</span><span id='textcolor2940'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> class *class, </span><span id='textcolor2941'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> class_attribute *attr,</span>
|
||||
<a id='x1-63043r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'> </span><span id='textcolor2942'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor2943'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *buf, </span><span id='textcolor2944'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> count);</span>
|
||||
<a id='x1-63045r7'></a><span class='ecrm-0500'>7</span><span class='ectt-0800'>};</span></pre>
|
||||
<!-- l. 1954 --><p class='indent'> In <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinput.c</span></span></span>, the macro <code> <span class='ectt-1000'>CLASS_ATTR_WO(export/unexport)</span>
|
||||
<!-- l. 1955 --><p class='indent'> In <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinput.c</span></span></span>, the macro <code> <span class='ectt-1000'>CLASS_ATTR_WO(export/unexport)</span>
|
||||
</code> defined in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/device.h'>include/linux/device.h</a> (in this case, <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>device.h</span></span></span> is included in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/input.h'>include/linux/input.h</a>)
|
||||
will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> structures which are named <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>class_attr_export/unexport</span></span></span>. Then, put them into
|
||||
@ -5669,14 +5670,14 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> that should be assigned in <code> <span class='ectt-1000'>vinput_class</span>
|
||||
</code>. Finally, call <code> <span class='ectt-1000'>class_register(&vinput_class)</span>
|
||||
</code> to create attributes in sysfs.
|
||||
</p><!-- l. 1958 --><p class='indent'> To create a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinputX</span></span></span> sysfs entry and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node.
|
||||
</p><!-- l. 1959 --><p class='indent'> To create a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinputX</span></span></span> sysfs entry and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb89'><a id='x1-63055r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor2946'><span class='ectt-1000'>"vkbd"</span></span><span class='ectt-1000'> | sudo tee /sys/class/vinput/export</span></pre>
|
||||
|
||||
|
||||
|
||||
<!-- l. 1964 --><p class='indent'> To unexport the device, just echo its id in unexport:
|
||||
<!-- l. 1965 --><p class='indent'> To unexport the device, just echo its id in unexport:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb90'><a id='x1-63058r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor2947'><span class='ectt-1000'>"0"</span></span><span class='ectt-1000'> | sudo tee /sys/class/vinput/unexport</span></pre>
|
||||
@ -6137,7 +6138,7 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
<a id='x1-63956r400'></a><span class='ecrm-0500'>400</span>
|
||||
<a id='x1-63958r401'></a><span class='ecrm-0500'>401</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3242'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-63960r402'></a><span class='ecrm-0500'>402</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3243'><span class='ectt-0800'>"Emulate input events"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1973 --><p class='indent'> Here the virtual keyboard is one of example to use vinput. It supports all
|
||||
<!-- l. 1974 --><p class='indent'> Here the virtual keyboard is one of example to use vinput. It supports all
|
||||
<code> <span class='ectt-1000'>KEY_MAX</span>
|
||||
</code> keycodes. The injection format is the <code> <span class='ectt-1000'>KEY_CODE</span>
|
||||
</code> such as defined in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/input.h'>include/linux/input.h</a>. A positive value means
|
||||
@ -6145,12 +6146,12 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> while a negative value is a <code> <span class='ectt-1000'>KEY_RELEASE</span>
|
||||
</code>. The keyboard supports repetition when the key stays pressed for too long. The
|
||||
following demonstrates how simulation work.
|
||||
</p><!-- l. 1980 --><p class='indent'> Simulate a key press on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</p><!-- l. 1981 --><p class='indent'> Simulate a key press on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</code> = 34):
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb93'><a id='x1-63968r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor3244'><span class='ectt-1000'>"+34"</span></span><span class='ectt-1000'> | sudo tee /dev/vinput0</span></pre>
|
||||
<!-- l. 1986 --><p class='indent'> Simulate a key release on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
<!-- l. 1987 --><p class='indent'> Simulate a key release on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</code> = 34):
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -6268,13 +6269,13 @@ following demonstrates how simulation work.
|
||||
<a id='x1-64188r108'></a><span class='ecrm-0500'>108</span>
|
||||
<a id='x1-64190r109'></a><span class='ecrm-0500'>109</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3327'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-64192r110'></a><span class='ecrm-0500'>110</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3328'><span class='ectt-0800'>"Emulate keyboard input events through /dev/vinput"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1996 --><p class='noindent'>
|
||||
<!-- l. 1997 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h3 class='sectionHead' id='standardizing-the-interfaces-the-device-model'><span class='titlemark'>18 </span> <a id='x1-6500018'></a>Standardizing the interfaces: The Device Model</h3>
|
||||
<!-- l. 1998 --><p class='noindent'>Up to this point we have seen all kinds of modules doing all kinds of things, but there
|
||||
<!-- l. 1999 --><p class='noindent'>Up to this point we have seen all kinds of modules doing all kinds of things, but there
|
||||
was no consistency in their interfaces with the rest of the kernel. To impose some
|
||||
consistency such that there is at minimum a standardized way to start, suspend and
|
||||
resume a device a device model was added. An example is shown below, and you can
|
||||
@ -6381,13 +6382,13 @@ functions.
|
||||
<a id='x1-65194r97'></a><span class='ecrm-0500'>97</span>
|
||||
<a id='x1-65196r98'></a><span class='ecrm-0500'>98</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3403'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-65198r99'></a><span class='ecrm-0500'>99</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3404'><span class='ectt-0800'>"Linux Device Model example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 2004 --><p class='noindent'>
|
||||
<!-- l. 2005 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='optimizations'><span class='titlemark'>19 </span> <a id='x1-6600019'></a>Optimizations</h3>
|
||||
<!-- l. 2006 --><p class='noindent'>
|
||||
<!-- l. 2007 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='likely-and-unlikely-conditions'><span class='titlemark'>19.1 </span> <a id='x1-6700019.1'></a>Likely and Unlikely conditions</h4>
|
||||
<!-- l. 2008 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible,
|
||||
<!-- l. 2009 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible,
|
||||
especially if it is handling an interrupt or doing something which might
|
||||
cause noticeable latency. If your code contains boolean conditions and if
|
||||
you know that the conditions are almost always likely to evaluate as either
|
||||
@ -6406,7 +6407,7 @@ to succeed.
|
||||
<a id='x1-67018r4'></a><span class='ecrm-0500'>4</span><span class='ectt-0800'> bio = NULL;</span>
|
||||
<a id='x1-67020r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor3406'><span class='ectt-0800'>goto</span></span><span class='ectt-0800'> out;</span>
|
||||
<a id='x1-67022r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 2022 --><p class='indent'> When the <code> <span class='ectt-1000'>unlikely</span>
|
||||
<!-- l. 2023 --><p class='indent'> When the <code> <span class='ectt-1000'>unlikely</span>
|
||||
</code> macro is used, the compiler alters its machine instruction output, so that it
|
||||
continues along the false branch and only jumps if the condition is true. That
|
||||
avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
@ -6415,34 +6416,34 @@ avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 2026 --><p class='noindent'>
|
||||
</p><!-- l. 2027 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='common-pitfalls'><span class='titlemark'>20 </span> <a id='x1-6800020'></a>Common Pitfalls</h3>
|
||||
<!-- l. 2029 --><p class='noindent'>
|
||||
<!-- l. 2030 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='using-standard-libraries'><span class='titlemark'>20.1 </span> <a id='x1-6900020.1'></a>Using standard libraries</h4>
|
||||
<!-- l. 2031 --><p class='noindent'>You can not do that. In a kernel module, you can only use kernel functions which are
|
||||
<!-- l. 2032 --><p class='noindent'>You can not do that. In a kernel module, you can only use kernel functions which are
|
||||
the functions you can see in <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/proc/kallsyms</span></span></span>.
|
||||
</p><!-- l. 2034 --><p class='noindent'>
|
||||
</p><!-- l. 2035 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='disabling-interrupts'><span class='titlemark'>20.2 </span> <a id='x1-7000020.2'></a>Disabling interrupts</h4>
|
||||
<!-- l. 2036 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you do not enable
|
||||
<!-- l. 2037 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you do not enable
|
||||
them afterwards, your system will be stuck and you will have to power it
|
||||
off.
|
||||
</p><!-- l. 2038 --><p class='noindent'>
|
||||
</p><!-- l. 2039 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='where-to-go-from-here'><span class='titlemark'>21 </span> <a id='x1-7100021'></a>Where To Go From Here?</h3>
|
||||
<!-- l. 2040 --><p class='noindent'>For people seriously interested in kernel programming, I recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a>
|
||||
<!-- l. 2041 --><p class='noindent'>For people seriously interested in kernel programming, I recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a>
|
||||
and the <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation'>Documentation</a> subdirectory within the kernel source code which is not
|
||||
always easy to understand but can be a starting point for further investigation. Also,
|
||||
as Linus Torvalds said, the best way to learn the kernel is to read the source code
|
||||
yourself.
|
||||
</p><!-- l. 2043 --><p class='indent'> If you would like to contribute to this guide or notice anything glaringly wrong,
|
||||
</p><!-- l. 2044 --><p class='indent'> If you would like to contribute to this guide or notice anything glaringly wrong,
|
||||
please create an issue at <a class='url' href='https://github.com/sysprog21/lkmpg'><span class='ectt-1000'>https://github.com/sysprog21/lkmpg</span></a>. Your pull requests
|
||||
will be appreciated.
|
||||
</p><!-- l. 2046 --><p class='indent'> Happy hacking!
|
||||
</p><!-- l. 2047 --><p class='indent'> Happy hacking!
|
||||
</p>
|
||||
<div class='footnotes'><!-- l. 1783 --><p class='indent'> <span class='footnote-mark'><a href='#fn1x0-bk' id='fn1x0'><sup class='textsuperscript'>1</sup></a></span><span class='ecrm-0800'>The goal of threaded interrupts is to push more of the work to separate threads, so that the
|
||||
<div class='footnotes'><!-- l. 1784 --><p class='indent'> <span class='footnote-mark'><a href='#fn1x0-bk' id='fn1x0'><sup class='textsuperscript'>1</sup></a></span><span class='ecrm-0800'>The goal of threaded interrupts is to push more of the work to separate threads, so that the
|
||||
</span><span class='ecrm-0800'>minimum needed for acknowledging an interrupt is reduced, and therefore the time spent handling
|
||||
</span><span class='ecrm-0800'>the interrupt (where it can’t handle any other interrupts at the same time) is reduced. See</span>
|
||||
<a class='url' href='https://lwn.net/Articles/302043/'><span class='ectt-0800'>https://lwn.net/Articles/302043/</span></a><span class='ecrm-0800'>.</span></p> </div>
|
||||
|
@ -4769,9 +4769,10 @@ better suited to running multiple things in a sequence.
|
||||
<h4 class='subsectionHead' id='tasklets'><span class='titlemark'>14.1 </span> <a id='x1-5400014.1'></a>Tasklets</h4>
|
||||
<!-- l. 1765 --><p class='noindent'>Here is an example tasklet module. The
|
||||
<code> <span class='ectt-1000'>tasklet_fn</span>
|
||||
</code> function runs for a few seconds and in the mean time execution of the
|
||||
</code> function runs for a few seconds. In the meantime, execution of the
|
||||
<code> <span class='ectt-1000'>example_tasklet_init</span>
|
||||
</code> function continues to the exit point.
|
||||
</code> function may continue to the exit point, depending on whether it is interrupted by
|
||||
<span class='ecbx-1000'>softirq</span>.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb77'><a id='x1-54004r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2403'><span class='ectt-0800'>/*</span></span>
|
||||
@ -4818,7 +4819,7 @@ better suited to running multiple things in a sequence.
|
||||
<a id='x1-54086r42'></a><span class='ecrm-0500'>42</span>
|
||||
<a id='x1-54088r43'></a><span class='ecrm-0500'>43</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2447'><span class='ectt-0800'>"Tasklet example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-54090r44'></a><span class='ecrm-0500'>44</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2448'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1770 --><p class='indent'> So with this example loaded <code> <span class='ectt-1000'>dmesg</span>
|
||||
<!-- l. 1771 --><p class='indent'> So with this example loaded <code> <span class='ectt-1000'>dmesg</span>
|
||||
</code> should show:
|
||||
|
||||
|
||||
@ -4830,23 +4831,23 @@ Example tasklet starts
|
||||
Example tasklet init continues...
|
||||
Example tasklet ends
|
||||
</pre>
|
||||
<!-- l. 1777 --><p class='nopar'>Although tasklet is easy to use, it comes with several defators, and developers are
|
||||
<!-- l. 1778 --><p class='nopar'>Although tasklet is easy to use, it comes with several defators, and developers are
|
||||
discussing about getting rid of tasklet in linux kernel. The tasklet callback
|
||||
runs in atomic context, inside a software interrupt, meaning that it cannot
|
||||
sleep or access user-space data, so not all work can be done in a tasklet
|
||||
handler. Also, the kernel only allows one instance of any given tasklet to be
|
||||
running at any given time; multiple different tasklet callbacks can run in
|
||||
parallel.
|
||||
</p><!-- l. 1782 --><p class='indent'> In recent kernels, tasklets can be replaced by workqueues, timers, or threaded
|
||||
</p><!-- l. 1783 --><p class='indent'> In recent kernels, tasklets can be replaced by workqueues, timers, or threaded
|
||||
interrupts.<span class='footnote-mark'><a href='#fn1x0' id='fn1x0-bk'><sup class='textsuperscript'>1</sup></a></span><a id='x1-54092f1'></a>
|
||||
While the removal of tasklets remains a longer-term goal, the current kernel contains more
|
||||
than a hundred uses of tasklets. Now developers are proceeding with the API changes and
|
||||
the macro <code> <span class='ectt-1000'>DECLARE_TASKLET_OLD</span>
|
||||
</code> exists for compatibility. For further information, see <a class='url' href='https://lwn.net/Articles/830964/'><span class='ectt-1000'>https://lwn.net/Articles/830964/</span></a>.
|
||||
</p><!-- l. 1788 --><p class='noindent'>
|
||||
</p><!-- l. 1789 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='work-queues'><span class='titlemark'>14.2 </span> <a id='x1-5500014.2'></a>Work queues</h4>
|
||||
<!-- l. 1790 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
<!-- l. 1791 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4883,36 +4884,36 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
<a id='x1-55062r31'></a><span class='ecrm-0500'>31</span>
|
||||
<a id='x1-55064r32'></a><span class='ecrm-0500'>32</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2476'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-55066r33'></a><span class='ecrm-0500'>33</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2477'><span class='ectt-0800'>"Workqueue example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1795 --><p class='noindent'>
|
||||
<!-- l. 1796 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='interrupt-handlers'><span class='titlemark'>15 </span> <a id='x1-5600015'></a>Interrupt Handlers</h3>
|
||||
<!-- l. 1797 --><p class='noindent'>
|
||||
<!-- l. 1798 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4 class='subsectionHead' id='interrupt-handlers1'><span class='titlemark'>15.1 </span> <a id='x1-5700015.1'></a>Interrupt Handlers</h4>
|
||||
<!-- l. 1799 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we have done as a
|
||||
<!-- l. 1800 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we have done as a
|
||||
response to a process asking for it, either by dealing with a special file, sending an
|
||||
<code> <span class='ectt-1000'>ioctl()</span>
|
||||
</code>, or issuing a system call. But the job of the kernel is not just to respond to process
|
||||
requests. Another job, which is every bit as important, is to speak to the hardware
|
||||
connected to the machine.
|
||||
</p><!-- l. 1803 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
</p><!-- l. 1804 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
computer’s hardware. The first type is when the CPU gives orders to the hardware,
|
||||
the order is when the hardware needs to tell the CPU something. The second, called
|
||||
interrupts, is much harder to implement because it has to be dealt with when
|
||||
convenient for the hardware, not the CPU. Hardware devices typically have a very
|
||||
small amount of RAM, and if you do not read their information when available, it is
|
||||
lost.
|
||||
</p><!-- l. 1808 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
</p><!-- l. 1809 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
are two types of IRQ’s, short and long. A short IRQ is one which is expected to take
|
||||
a very short period of time, during which the rest of the machine will be blocked and
|
||||
no other interrupts will be handled. A long IRQ is one which can take longer, and
|
||||
during which other interrupts may occur (but not interrupts from the same
|
||||
device). If at all possible, it is better to declare an interrupt handler to be
|
||||
long.
|
||||
</p><!-- l. 1814 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it is doing (unless it is
|
||||
</p><!-- l. 1815 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it is doing (unless it is
|
||||
processing a more important interrupt, in which case it will deal with this one only
|
||||
when the more important one is done), saves certain parameters on the stack and
|
||||
calls the interrupt handler. This means that certain things are not allowed in the
|
||||
@ -4924,10 +4925,10 @@ heavy work deferred from an interrupt handler. Historically, BH (Linux
|
||||
naming for <span class='ecti-1000'>Bottom Halves</span>) statistically book-keeps the deferred functions.
|
||||
<span class='ecbx-1000'>Softirq </span>and its higher level abstraction, <span class='ecbx-1000'>Tasklet</span>, replace BH since Linux
|
||||
2.3.
|
||||
</p><!-- l. 1824 --><p class='indent'> The way to implement this is to call
|
||||
</p><!-- l. 1825 --><p class='indent'> The way to implement this is to call
|
||||
<code> <span class='ectt-1000'>request_irq()</span>
|
||||
</code> to get your interrupt handler called when the relevant IRQ is received.
|
||||
</p><!-- l. 1826 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
</p><!-- l. 1827 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
designed in a way that chains two interrupt controllers, so that all the IRQs
|
||||
from interrupt controller B are cascaded to a certain IRQ from interrupt
|
||||
controller A. Of course, that requires that the kernel finds out which IRQ it
|
||||
@ -4944,7 +4945,7 @@ need to solve another truckload of problems. It is not enough to know if a
|
||||
certain IRQs has happened, it’s also important to know what CPU(s) it was
|
||||
for. People still interested in more details, might want to refer to "APIC"
|
||||
now.
|
||||
</p><!-- l. 1835 --><p class='indent'> This function receives the IRQ number, the name of the function,
|
||||
</p><!-- l. 1836 --><p class='indent'> This function receives the IRQ number, the name of the function,
|
||||
flags, a name for <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/proc/interrupts</span></span></span> and a parameter to be passed to the
|
||||
interrupt handler. Usually there is a certain number of IRQs available.
|
||||
How many IRQs there are is hardware-dependent. The flags can include
|
||||
@ -4954,16 +4955,16 @@ How many IRQs there are is hardware-dependent. The flags can include
|
||||
<code> <span class='ectt-1000'>SA_INTERRUPT</span>
|
||||
</code> to indicate this is a fast interrupt. This function will only succeed if there is not
|
||||
already a handler on this IRQ, or if you are both willing to share.
|
||||
</p><!-- l. 1841 --><p class='noindent'>
|
||||
</p><!-- l. 1842 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='detecting-button-presses'><span class='titlemark'>15.2 </span> <a id='x1-5800015.2'></a>Detecting button presses</h4>
|
||||
<!-- l. 1843 --><p class='noindent'>Many popular single board computers, such as Raspberry Pi or Beagleboards, have a
|
||||
<!-- l. 1844 --><p class='noindent'>Many popular single board computers, such as Raspberry Pi or Beagleboards, have a
|
||||
bunch of GPIO pins. Attaching buttons to those and then having a button press do
|
||||
something is a classic case in which you might need to use interrupts, so that instead
|
||||
of having the CPU waste time and battery power polling for a change in input state,
|
||||
it is better for the input to trigger the CPU to then run a particular handling
|
||||
function.
|
||||
</p><!-- l. 1847 --><p class='indent'> Here is an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
</p><!-- l. 1848 --><p class='indent'> Here is an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
an LED is connected to GPIO 4. You can change those numbers to whatever is
|
||||
appropriate for your board.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -5112,14 +5113,14 @@ appropriate for your board.
|
||||
<a id='x1-58284r142'></a><span class='ecrm-0500'>142</span>
|
||||
<a id='x1-58286r143'></a><span class='ecrm-0500'>143</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2584'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-58288r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2585'><span class='ectt-0800'>"Handle some GPIO interrupts"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1852 --><p class='noindent'>
|
||||
<!-- l. 1853 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='bottom-half'><span class='titlemark'>15.3 </span> <a id='x1-5900015.3'></a>Bottom Half</h4>
|
||||
<!-- l. 1854 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
<!-- l. 1855 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
way to do that without rendering the interrupt unavailable for a significant duration
|
||||
is to combine it with a tasklet. This pushes the bulk of the work off into the
|
||||
scheduler.
|
||||
</p><!-- l. 1858 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
</p><!-- l. 1859 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
when an interrupt is triggered.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -5293,19 +5294,19 @@ when an interrupt is triggered.
|
||||
<a id='x1-59330r165'></a><span class='ecrm-0500'>165</span>
|
||||
<a id='x1-59332r166'></a><span class='ecrm-0500'>166</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2713'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-59334r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2714'><span class='ectt-0800'>"Interrupt with top and bottom half"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1862 --><p class='noindent'>
|
||||
<!-- l. 1863 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='crypto'><span class='titlemark'>16 </span> <a id='x1-6000016'></a>Crypto</h3>
|
||||
<!-- l. 1864 --><p class='noindent'>At the dawn of the internet, everybody trusted everybody completely…but that did
|
||||
<!-- l. 1865 --><p class='noindent'>At the dawn of the internet, everybody trusted everybody completely…but that did
|
||||
not work out so well. When this guide was originally written, it was a more innocent
|
||||
era in which almost nobody actually gave a damn about crypto - least of all kernel
|
||||
developers. That is certainly no longer the case now. To handle crypto stuff, the
|
||||
kernel has its own API enabling common methods of encryption, decryption and your
|
||||
favourite hash functions.
|
||||
</p><!-- l. 1869 --><p class='noindent'>
|
||||
</p><!-- l. 1870 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='hash-functions'><span class='titlemark'>16.1 </span> <a id='x1-6100016.1'></a>Hash functions</h4>
|
||||
<!-- l. 1872 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
<!-- l. 1873 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5373,20 +5374,20 @@ demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
<a id='x1-61124r62'></a><span class='ecrm-0500'>62</span>
|
||||
<a id='x1-61126r63'></a><span class='ecrm-0500'>63</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2766'><span class='ectt-0800'>"sha256 hash test"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-61128r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2767'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1877 --><p class='indent'> Install the module:
|
||||
<!-- l. 1878 --><p class='indent'> Install the module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb82'><a id='x1-61132r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo insmod cryptosha256.ko</span>
|
||||
<a id='x1-61134r2'></a><span class='ecrm-0500'>2</span><span class='ectt-1000'>sudo dmesg</span></pre>
|
||||
<!-- l. 1884 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1886 --><p class='indent'> Finally, remove the test module:
|
||||
<!-- l. 1885 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1887 --><p class='indent'> Finally, remove the test module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb83'><a id='x1-61137r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo rmmod cryptosha256</span></pre>
|
||||
<!-- l. 1892 --><p class='noindent'>
|
||||
<!-- l. 1893 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='symmetric-key-encryption'><span class='titlemark'>16.2 </span> <a id='x1-6200016.2'></a>Symmetric key encryption</h4>
|
||||
<!-- l. 1894 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
<!-- l. 1895 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
and a password.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -5591,10 +5592,10 @@ and a password.
|
||||
<a id='x1-62392r196'></a><span class='ecrm-0500'>196</span>
|
||||
<a id='x1-62394r197'></a><span class='ecrm-0500'>197</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2919'><span class='ectt-0800'>"Symmetric key encryption example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-62396r198'></a><span class='ecrm-0500'>198</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2920'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1898 --><p class='noindent'>
|
||||
<!-- l. 1899 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='virtual-input-device-driver'><span class='titlemark'>17 </span> <a id='x1-6300017'></a>Virtual Input Device Driver</h3>
|
||||
<!-- l. 1900 --><p class='noindent'>The input device driver is a module that provides a way to communicate
|
||||
<!-- l. 1901 --><p class='noindent'>The input device driver is a module that provides a way to communicate
|
||||
with the interaction device via the event. For example, the keyboard
|
||||
can send the press or release event to tell the kernel what we want to
|
||||
do. The input device driver will allocate a new input structure with
|
||||
@ -5602,7 +5603,7 @@ do. The input device driver will allocate a new input structure with
|
||||
</code> and sets up input bitfields, device id, version, etc. After that, registers it by calling
|
||||
<code> <span class='ectt-1000'>input_register_device()</span>
|
||||
</code>.
|
||||
</p><!-- l. 1905 --><p class='indent'> Here is an example, vinput, It is an API to allow easy
|
||||
</p><!-- l. 1906 --><p class='indent'> Here is an example, vinput, It is an API to allow easy
|
||||
development of virtual input drivers. The drivers needs to export a
|
||||
<code> <span class='ectt-1000'>vinput_device()</span>
|
||||
</code> that contains the virtual device name and
|
||||
@ -5618,7 +5619,7 @@ development of virtual input drivers. The drivers needs to export a
|
||||
</li>
|
||||
<li class='itemize'>the readback function: <code> <span class='ectt-1000'>read()</span>
|
||||
</code></li></ul>
|
||||
<!-- l. 1915 --><p class='indent'> Then using <code> <span class='ectt-1000'>vinput_register_device()</span>
|
||||
<!-- l. 1916 --><p class='indent'> Then using <code> <span class='ectt-1000'>vinput_register_device()</span>
|
||||
</code> and <code> <span class='ectt-1000'>vinput_unregister_device()</span>
|
||||
</code> will add a new device to the list of support virtual input devices.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -5627,7 +5628,7 @@ development of virtual input drivers. The drivers needs to export a
|
||||
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb85'><a id='x1-63012r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2921'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> init(</span><span id='textcolor2922'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *);</span></pre>
|
||||
<!-- l. 1921 --><p class='indent'> This function is passed a <code> <span id='textcolor2923'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> vinput</span>
|
||||
<!-- l. 1922 --><p class='indent'> This function is passed a <code> <span id='textcolor2923'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> vinput</span>
|
||||
</code> already initialized with an allocated <code> <span id='textcolor2924'><span class='ectt-1000'>struct</span></span><span class='ectt-1000'> input_dev</span>
|
||||
</code>. The <code> <span class='ectt-1000'>init()</span>
|
||||
</code> function is responsible for initializing the capabilities of the input device and register
|
||||
@ -5635,20 +5636,20 @@ it.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb86'><a id='x1-63018r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2925'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> send(</span><span id='textcolor2926'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *, </span><span id='textcolor2927'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *, </span><span id='textcolor2928'><span class='ectt-0800'>int</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1928 --><p class='indent'> This function will receive a user string to interpret and inject the event using the
|
||||
<!-- l. 1929 --><p class='indent'> This function will receive a user string to interpret and inject the event using the
|
||||
<code> <span class='ectt-1000'>input_report_XXXX</span>
|
||||
</code> or <code> <span class='ectt-1000'>input_event</span>
|
||||
</code> call. The string is already copied from user.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb87'><a id='x1-63023r1'></a><span class='ecrm-0500'>1</span><span id='textcolor2929'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> read(</span><span id='textcolor2930'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> vinput *, </span><span id='textcolor2931'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *, </span><span id='textcolor2932'><span class='ectt-0800'>int</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1935 --><p class='indent'> This function is used for debugging and should fill the buffer parameter with the
|
||||
<!-- l. 1936 --><p class='indent'> This function is used for debugging and should fill the buffer parameter with the
|
||||
last event sent in the virtual input device format. The buffer will then be copied to
|
||||
user.
|
||||
</p><!-- l. 1938 --><p class='indent'> vinput devices are created and destroyed using sysfs. And, event injection is done
|
||||
</p><!-- l. 1939 --><p class='indent'> vinput devices are created and destroyed using sysfs. And, event injection is done
|
||||
through a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node. The device name will be used by the userland to export a new
|
||||
virtual input device.
|
||||
</p><!-- l. 1942 --><p class='indent'> The <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</p><!-- l. 1943 --><p class='indent'> The <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> structure is similar to other attribute types we talked about in section <a href='#sysfs-interacting-with-your-module'>8<!-- tex4ht:ref: sec:sysfs --></a>:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5659,7 +5660,7 @@ virtual input device.
|
||||
<a id='x1-63041r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor2939'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> (*store)(</span><span id='textcolor2940'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> class *class, </span><span id='textcolor2941'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> class_attribute *attr,</span>
|
||||
<a id='x1-63043r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'> </span><span id='textcolor2942'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor2943'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *buf, </span><span id='textcolor2944'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> count);</span>
|
||||
<a id='x1-63045r7'></a><span class='ecrm-0500'>7</span><span class='ectt-0800'>};</span></pre>
|
||||
<!-- l. 1954 --><p class='indent'> In <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinput.c</span></span></span>, the macro <code> <span class='ectt-1000'>CLASS_ATTR_WO(export/unexport)</span>
|
||||
<!-- l. 1955 --><p class='indent'> In <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinput.c</span></span></span>, the macro <code> <span class='ectt-1000'>CLASS_ATTR_WO(export/unexport)</span>
|
||||
</code> defined in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/device.h'>include/linux/device.h</a> (in this case, <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>device.h</span></span></span> is included in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/input.h'>include/linux/input.h</a>)
|
||||
will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> structures which are named <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>class_attr_export/unexport</span></span></span>. Then, put them into
|
||||
@ -5669,14 +5670,14 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> that should be assigned in <code> <span class='ectt-1000'>vinput_class</span>
|
||||
</code>. Finally, call <code> <span class='ectt-1000'>class_register(&vinput_class)</span>
|
||||
</code> to create attributes in sysfs.
|
||||
</p><!-- l. 1958 --><p class='indent'> To create a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinputX</span></span></span> sysfs entry and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node.
|
||||
</p><!-- l. 1959 --><p class='indent'> To create a <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>vinputX</span></span></span> sysfs entry and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev</span></span></span> node.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb89'><a id='x1-63055r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor2946'><span class='ectt-1000'>"vkbd"</span></span><span class='ectt-1000'> | sudo tee /sys/class/vinput/export</span></pre>
|
||||
|
||||
|
||||
|
||||
<!-- l. 1964 --><p class='indent'> To unexport the device, just echo its id in unexport:
|
||||
<!-- l. 1965 --><p class='indent'> To unexport the device, just echo its id in unexport:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb90'><a id='x1-63058r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor2947'><span class='ectt-1000'>"0"</span></span><span class='ectt-1000'> | sudo tee /sys/class/vinput/unexport</span></pre>
|
||||
@ -6137,7 +6138,7 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
<a id='x1-63956r400'></a><span class='ecrm-0500'>400</span>
|
||||
<a id='x1-63958r401'></a><span class='ecrm-0500'>401</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3242'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-63960r402'></a><span class='ecrm-0500'>402</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3243'><span class='ectt-0800'>"Emulate input events"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1973 --><p class='indent'> Here the virtual keyboard is one of example to use vinput. It supports all
|
||||
<!-- l. 1974 --><p class='indent'> Here the virtual keyboard is one of example to use vinput. It supports all
|
||||
<code> <span class='ectt-1000'>KEY_MAX</span>
|
||||
</code> keycodes. The injection format is the <code> <span class='ectt-1000'>KEY_CODE</span>
|
||||
</code> such as defined in <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/input.h'>include/linux/input.h</a>. A positive value means
|
||||
@ -6145,12 +6146,12 @@ will generate the <code> <span class='ectt-1000'>class_attribute</span>
|
||||
</code> while a negative value is a <code> <span class='ectt-1000'>KEY_RELEASE</span>
|
||||
</code>. The keyboard supports repetition when the key stays pressed for too long. The
|
||||
following demonstrates how simulation work.
|
||||
</p><!-- l. 1980 --><p class='indent'> Simulate a key press on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</p><!-- l. 1981 --><p class='indent'> Simulate a key press on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</code> = 34):
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb93'><a id='x1-63968r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo </span><span id='textcolor3244'><span class='ectt-1000'>"+34"</span></span><span class='ectt-1000'> | sudo tee /dev/vinput0</span></pre>
|
||||
<!-- l. 1986 --><p class='indent'> Simulate a key release on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
<!-- l. 1987 --><p class='indent'> Simulate a key release on "g" (<code> <span class='ectt-1000'>KEY_G</span>
|
||||
</code> = 34):
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -6268,13 +6269,13 @@ following demonstrates how simulation work.
|
||||
<a id='x1-64188r108'></a><span class='ecrm-0500'>108</span>
|
||||
<a id='x1-64190r109'></a><span class='ecrm-0500'>109</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3327'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-64192r110'></a><span class='ecrm-0500'>110</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3328'><span class='ectt-0800'>"Emulate keyboard input events through /dev/vinput"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1996 --><p class='noindent'>
|
||||
<!-- l. 1997 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h3 class='sectionHead' id='standardizing-the-interfaces-the-device-model'><span class='titlemark'>18 </span> <a id='x1-6500018'></a>Standardizing the interfaces: The Device Model</h3>
|
||||
<!-- l. 1998 --><p class='noindent'>Up to this point we have seen all kinds of modules doing all kinds of things, but there
|
||||
<!-- l. 1999 --><p class='noindent'>Up to this point we have seen all kinds of modules doing all kinds of things, but there
|
||||
was no consistency in their interfaces with the rest of the kernel. To impose some
|
||||
consistency such that there is at minimum a standardized way to start, suspend and
|
||||
resume a device a device model was added. An example is shown below, and you can
|
||||
@ -6381,13 +6382,13 @@ functions.
|
||||
<a id='x1-65194r97'></a><span class='ecrm-0500'>97</span>
|
||||
<a id='x1-65196r98'></a><span class='ecrm-0500'>98</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3403'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-65198r99'></a><span class='ecrm-0500'>99</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor3404'><span class='ectt-0800'>"Linux Device Model example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 2004 --><p class='noindent'>
|
||||
<!-- l. 2005 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='optimizations'><span class='titlemark'>19 </span> <a id='x1-6600019'></a>Optimizations</h3>
|
||||
<!-- l. 2006 --><p class='noindent'>
|
||||
<!-- l. 2007 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='likely-and-unlikely-conditions'><span class='titlemark'>19.1 </span> <a id='x1-6700019.1'></a>Likely and Unlikely conditions</h4>
|
||||
<!-- l. 2008 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible,
|
||||
<!-- l. 2009 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible,
|
||||
especially if it is handling an interrupt or doing something which might
|
||||
cause noticeable latency. If your code contains boolean conditions and if
|
||||
you know that the conditions are almost always likely to evaluate as either
|
||||
@ -6406,7 +6407,7 @@ to succeed.
|
||||
<a id='x1-67018r4'></a><span class='ecrm-0500'>4</span><span class='ectt-0800'> bio = NULL;</span>
|
||||
<a id='x1-67020r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor3406'><span class='ectt-0800'>goto</span></span><span class='ectt-0800'> out;</span>
|
||||
<a id='x1-67022r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 2022 --><p class='indent'> When the <code> <span class='ectt-1000'>unlikely</span>
|
||||
<!-- l. 2023 --><p class='indent'> When the <code> <span class='ectt-1000'>unlikely</span>
|
||||
</code> macro is used, the compiler alters its machine instruction output, so that it
|
||||
continues along the false branch and only jumps if the condition is true. That
|
||||
avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
@ -6415,34 +6416,34 @@ avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 2026 --><p class='noindent'>
|
||||
</p><!-- l. 2027 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='common-pitfalls'><span class='titlemark'>20 </span> <a id='x1-6800020'></a>Common Pitfalls</h3>
|
||||
<!-- l. 2029 --><p class='noindent'>
|
||||
<!-- l. 2030 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='using-standard-libraries'><span class='titlemark'>20.1 </span> <a id='x1-6900020.1'></a>Using standard libraries</h4>
|
||||
<!-- l. 2031 --><p class='noindent'>You can not do that. In a kernel module, you can only use kernel functions which are
|
||||
<!-- l. 2032 --><p class='noindent'>You can not do that. In a kernel module, you can only use kernel functions which are
|
||||
the functions you can see in <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/proc/kallsyms</span></span></span>.
|
||||
</p><!-- l. 2034 --><p class='noindent'>
|
||||
</p><!-- l. 2035 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='disabling-interrupts'><span class='titlemark'>20.2 </span> <a id='x1-7000020.2'></a>Disabling interrupts</h4>
|
||||
<!-- l. 2036 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you do not enable
|
||||
<!-- l. 2037 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you do not enable
|
||||
them afterwards, your system will be stuck and you will have to power it
|
||||
off.
|
||||
</p><!-- l. 2038 --><p class='noindent'>
|
||||
</p><!-- l. 2039 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='where-to-go-from-here'><span class='titlemark'>21 </span> <a id='x1-7100021'></a>Where To Go From Here?</h3>
|
||||
<!-- l. 2040 --><p class='noindent'>For people seriously interested in kernel programming, I recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a>
|
||||
<!-- l. 2041 --><p class='noindent'>For people seriously interested in kernel programming, I recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a>
|
||||
and the <a href='https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation'>Documentation</a> subdirectory within the kernel source code which is not
|
||||
always easy to understand but can be a starting point for further investigation. Also,
|
||||
as Linus Torvalds said, the best way to learn the kernel is to read the source code
|
||||
yourself.
|
||||
</p><!-- l. 2043 --><p class='indent'> If you would like to contribute to this guide or notice anything glaringly wrong,
|
||||
</p><!-- l. 2044 --><p class='indent'> If you would like to contribute to this guide or notice anything glaringly wrong,
|
||||
please create an issue at <a class='url' href='https://github.com/sysprog21/lkmpg'><span class='ectt-1000'>https://github.com/sysprog21/lkmpg</span></a>. Your pull requests
|
||||
will be appreciated.
|
||||
</p><!-- l. 2046 --><p class='indent'> Happy hacking!
|
||||
</p><!-- l. 2047 --><p class='indent'> Happy hacking!
|
||||
</p>
|
||||
<div class='footnotes'><!-- l. 1783 --><p class='indent'> <span class='footnote-mark'><a href='#fn1x0-bk' id='fn1x0'><sup class='textsuperscript'>1</sup></a></span><span class='ecrm-0800'>The goal of threaded interrupts is to push more of the work to separate threads, so that the
|
||||
<div class='footnotes'><!-- l. 1784 --><p class='indent'> <span class='footnote-mark'><a href='#fn1x0-bk' id='fn1x0'><sup class='textsuperscript'>1</sup></a></span><span class='ecrm-0800'>The goal of threaded interrupts is to push more of the work to separate threads, so that the
|
||||
</span><span class='ecrm-0800'>minimum needed for acknowledging an interrupt is reduced, and therefore the time spent handling
|
||||
</span><span class='ecrm-0800'>the interrupt (where it can’t handle any other interrupts at the same time) is reduced. See</span>
|
||||
<a class='url' href='https://lwn.net/Articles/302043/'><span class='ectt-0800'>https://lwn.net/Articles/302043/</span></a><span class='ecrm-0800'>.</span></p> </div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user