blob: 93cbc864bafba8a09fef653ab1d4a835ba5e50c8 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Removing Device Drivers with NSH &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/sphinx_collapse.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css" />
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<script src="../_static/jquery.js"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Rust in NuttX" href="rust.html" />
<link rel="prev" title="Reading CAN Messages" href="reading_can_msgs.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../latest" selected="selected">latest</option>
<option value="../../10.0.0" >10.0.0</option>
<option value="../../10.0.1" >10.0.1</option>
<option value="../../10.1.0" >10.1.0</option>
<option value="../../10.2.0" >10.2.0</option>
<option value="../../10.3.0" >10.3.0</option>
<option value="../../11.0.0" >11.0.0</option>
<option value="../../12.0.0" >12.0.0</option>
<option value="../../12.1.0" >12.1.0</option>
<option value="../../12.2.0" >12.2.0</option>
<option value="../../12.2.1" >12.2.1</option>
<option value="../../12.3.0" >12.3.0</option>
<option value="../../12.4.0" >12.4.0</option>
<option value="../../12.5.0" >12.5.0</option>
<option value="../../12.5.1" >12.5.1</option>
<option value="../../12.6.0" >12.6.0</option>
<option value="../../12.7.0" >12.7.0</option>
<option value="../../12.8.0" >12.8.0</option>
<option value="../../12.9.0" >12.9.0</option>
<option value="../../12.10.0" >12.10.0</option>
<option value="../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li>
<li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../debugging/index.html">Debugging</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="nix_flake.html">Nix Flake for Reproducible Development</a></li>
<li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li>
<li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li>
<li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li>
<li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li>
<li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li>
<li class="toctree-l2"><a class="reference internal" href="zerolatencyinterrupts.html">High Performance: Zero Latency Interrupts, Maskable Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="fortify.html">Fortify</a></li>
<li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32ccm.html">STM32 CCM Allocator</a></li>
<li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li>
<li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li>
<li class="toctree-l2"><a class="reference internal" href="devicetree.html">Device Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="changing_systemclockconfig.html">Changing the System Clock Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="usingkernelthreads.html">Using Kernel Threads</a></li>
<li class="toctree-l2"><a class="reference internal" href="armv7m_runtimestackcheck.html">ARMv7-M Run Time Stack Checking</a></li>
<li class="toctree-l2"><a class="reference internal" href="include_files_board_h.html">Including Files in board.h</a></li>
<li class="toctree-l2"><a class="reference internal" href="specialstuff_in_nuttxheaderfiles.html">Why can’t I put my special stuff in NuttX header files?</a></li>
<li class="toctree-l2"><a class="reference internal" href="kernel_threads_with_custom_stacks.html">Kernel Threads with Custom Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="versioning_and_task_names.html">Versioning and Task Names</a></li>
<li class="toctree-l2"><a class="reference internal" href="logging_rambuffer.html">Logging to a RAM Buffer</a></li>
<li class="toctree-l2"><a class="reference internal" href="ipv6.html">IPv6</a></li>
<li class="toctree-l2"><a class="reference internal" href="integrate_newlib.html">Integrating with Newlib</a></li>
<li class="toctree-l2"><a class="reference internal" href="protected_build.html">NuttX Protected Build</a></li>
<li class="toctree-l2"><a class="reference internal" href="platform_directories.html">Platform Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="port_drivers_to_stm32f7.html">Porting Drivers to the STM32 F7</a></li>
<li class="toctree-l2"><a class="reference internal" href="semihosting.html">Semihosting</a></li>
<li class="toctree-l2"><a class="reference internal" href="renode.html">Run NuttX on Renode</a></li>
<li class="toctree-l2"><a class="reference internal" href="signal_events_interrupt_handlers.html">Signaling Events from Interrupt Handlers</a></li>
<li class="toctree-l2"><a class="reference internal" href="signaling_sem_priority_inheritance.html">Signaling Semaphores and Priority Inheritance</a></li>
<li class="toctree-l2"><a class="reference internal" href="smaller_vector_tables.html">Smaller Vector Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="port.html">How to port</a></li>
<li class="toctree-l2"><a class="reference internal" href="updating_release_system_elf.html">Updating a Release System with ELF Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="partially_linked_elf.html">ELF Programs – With Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="fully_linked_elf.html">ELF Programs – No Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_nuttx_with_app_out_of_src_tree.html">Building NuttX with Applications Outside the Source Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_uclibcpp.html">Building uClibc++</a></li>
<li class="toctree-l2"><a class="reference internal" href="custom_app_directories.html">Custom Application Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="multiple_nsh_sessions.html">Multiple NSH Sessions</a></li>
<li class="toctree-l2"><a class="reference internal" href="nsh_network_link_management.html">NSH Network Link Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="ram_rom_disks.html">RAM Disks and ROM Disks</a></li>
<li class="toctree-l2"><a class="reference internal" href="reading_can_msgs.html">Reading CAN Messages</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Removing Device Drivers with NSH</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#nuttx-and-unix-like-operating-systems-compared">NuttX and Unix-like Operating Systems Compared</a></li>
<li class="toctree-l3"><a class="reference internal" href="#the-unlink-method">The unlink() Method</a></li>
<li class="toctree-l3"><a class="reference internal" href="#removing-a-device-node-from-nsh">Removing a Device Node from NSH</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="rust.html">Rust in NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="optee.html">Interfacing with OP-TEE</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../standards/index.html">Standards</a></li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../_tags/tagsindex.html">Tags</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="index.html">Guides</a></li>
<li class="breadcrumb-item active">Removing Device Drivers with NSH</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/nuttx/blob/master/Documentation/guides/remove_device_drivers_nsh.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="removing-device-drivers-with-nsh">
<h1>Removing Device Drivers with NSH<a class="headerlink" href="#removing-device-drivers-with-nsh" title="Permalink to this heading"></a></h1>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Migrated from:
<a class="reference external" href="https://cwiki.apache.org/confluence/display/NUTTX/Removing+Device+Drivers+with+NSH">https://cwiki.apache.org/confluence/display/NUTTX/Removing+Device+Drivers+with+NSH</a></p>
</div>
<section id="nuttx-and-unix-like-operating-systems-compared">
<h2>NuttX and Unix-like Operating Systems Compared<a class="headerlink" href="#nuttx-and-unix-like-operating-systems-compared" title="Permalink to this heading"></a></h2>
<p>There are many things that are called device drivers. In this context, the
discussion is limited to <strong>character device drivers</strong>. In NuttX, character
device drivers are represented by device driver nodes in the top-level <a class="reference internal" href="../components/filesystem/pseudofs.html"><span class="doc">pseudo
filesystem</span></a>.</p>
<p>Standard Unix-like operating systems also support device driver nodes, which
superficially resemble NuttX device driver nodes: Both look like files and
usually reside under the top-level <code class="docutils literal notranslate"><span class="pre">/dev</span></code> directory. Both can be accessed
with standard POSIX file system commands such as <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code>,
<code class="docutils literal notranslate"><span class="pre">read()</span></code>, <code class="docutils literal notranslate"><span class="pre">write()</span></code>, and so forth. However, the similarity ends there.</p>
<p>The payload of a standard Unix-like operating system device driver node is a
device major and minor number. These major and minor device numbers are used to
look up the actual device driver interface using internal OS logic and data
structures. A NuttX device node, by contrast, directly holds the device driver
interface with no intervening lookup. This design is less flexible, but it is
more efficient and conserves limited resources in an embedded system.</p>
<p>In standard Unix-like operating systems, the device node can simply be deleted
using the shell command <code class="docutils literal notranslate"><span class="pre">rm</span></code> or the programmatic interface <code class="docutils literal notranslate"><span class="pre">unlink()</span></code>. The
node is removed, and nothing special happens to the underlying device driver
(except that it may no longer be accessible).</p>
<p>In NuttX, if the device node were removed in the same way, the entire device
interface would also be removed, effectively breaking the driver. Internally,
NuttX supports a function called <code class="docutils literal notranslate"><span class="pre">unregister_driver()</span></code> that can be invoked
to remove a device driver. Therefore, removing the device driver node must
behave as though <code class="docutils literal notranslate"><span class="pre">unregister_driver()</span></code> were called.</p>
</section>
<section id="the-unlink-method">
<h2>The unlink() Method<a class="headerlink" href="#the-unlink-method" title="Permalink to this heading"></a></h2>
<p>How is this accomplished in NuttX? It is done via a special device driver
method called <code class="docutils literal notranslate"><span class="pre">unlink()</span></code>.</p>
<p>NuttX device drivers are implemented via a vtable of function pointers. That
vtable defines the interface between the pseudo-file system and the device
driver. This vtable is the structure <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">file_operations</span></code> defined in
<code class="docutils literal notranslate"><span class="pre">[nuttx]/include/nuttx/fs/fs.h</span></code>. It provides several interfaces that closely
match the standard POSIX interfaces—<code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code>, <code class="docutils literal notranslate"><span class="pre">read()</span></code>,
<code class="docutils literal notranslate"><span class="pre">write()</span></code>, etc.—and also includes a method called <code class="docutils literal notranslate"><span class="pre">unlink()</span></code>. This
<code class="docutils literal notranslate"><span class="pre">unlink()</span></code> method is called by the NuttX VFS when a user removes a device
driver node.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Removal of device driver nodes is only permitted if
<code class="docutils literal notranslate"><span class="pre">CONFIG_DISABLE_PSEUDOFS_OPERATIONS</span></code> is <strong>not</strong> defined. All pseudo-file
system operations may be suppressed to reduce the FLASH footprint in systems
with extremely limited resources.</p>
</div>
</section>
<section id="removing-a-device-node-from-nsh">
<h2>Removing a Device Node from NSH<a class="headerlink" href="#removing-a-device-node-from-nsh" title="Permalink to this heading"></a></h2>
<p>Below is a summary of what happens when a device node is deleted using the NSH
<code class="docutils literal notranslate"><span class="pre">rm</span></code> command:</p>
<ol class="arabic simple">
<li><p>The user enters the <code class="docutils literal notranslate"><span class="pre">rm</span></code> command. The NSH parser recognizes the command
and transfers control to the NSH function <code class="docutils literal notranslate"><span class="pre">cmd_rm()</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_rm()</span></code> verifies the command, then calls the standard POSIX
<code class="docutils literal notranslate"><span class="pre">unlink()</span></code> interface. The logic in the VFS <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> function in
<code class="docutils literal notranslate"><span class="pre">[nuttx]/fs/vfs/fs_unlink.c</span></code> is then executed.</p></li>
<li><p>The VFS <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> detects that the target to be removed is a device node
in the top-level pseudo-file system. It calls the device driver’s
<code class="docutils literal notranslate"><span class="pre">unlink()</span></code> method. It also removes the device node from the
pseudo-filesystem. However, the underlying resources required to support
the device driver interface may remain until the device driver frees those
resources.</p></li>
<li><p>When the device driver’s <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> method is called, it determines if
the device resources can be freed immediately. If so, it frees those
resources. If, for example, there are still open references to the device
driver, it may defer freeing the resources until the last client has closed
the device driver and there are no open references. In such a case, it may
set a flag indicating that the device driver has been unlinked.</p></li>
<li><p>If freeing of device driver resources has been deferred, that flag will be
examined later. For instance, when the last client of the device driver
closes its reference to the driver, it checks whether the unlink operation
was deferred. If so, it frees any remaining device driver resources at that
time.</p></li>
</ol>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Some character device driver instances do not implement the <code class="docutils literal notranslate"><span class="pre">unlink()</span></code>
method. If problems arise when attempting to remove character drivers as
described in this Wiki page, a missing <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> method is the most
likely cause.</p>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="reading_can_msgs.html" class="btn btn-neutral float-left" title="Reading CAN Messages" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="rust.html" class="btn btn-neutral float-right" title="Rust in NuttX" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>