% Copyright (C) 2018 TANSORIER. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU Free Documentation License, Version 1.3 % or any later version published by the Free Software Foundation; % with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. % A copy of the license is included in the section entitled "GNU % Free Documentation License". % https://www.gnu.org/licenses/fdl-1.3.html % compress option to have horyzontal circle \documentclass[compress,aspectratio=169]{beamer} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Thèmes suppélmentaires \useoutertheme[]{miniframes} % barre menu du haut \setbeamertemplate{frametitle}[default] % replace le titre à la bonne place \useinnertheme[shadow=true]{rounded} % arrondi les angles \usecolortheme{orchid} \usecolortheme{whale} %\usepackage{xcolor} %\definecolor{smileOrange}{RGB}{254,128,86} \setbeamertemplate{footline}[text line]{ \textcolor{gray}{% \parbox{\linewidth}{\vspace*{-8pt}Smile\hfill\insertshortauthor\hfill\insertpagenumber/\inserttotalframenumber}} } \beamertemplatenavigationsymbolsempty % Language \usepackage[french]{babel} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} %\usepackage[latin1]{inputenc} % Display Table Of Content spécific for smilebeamer % Force to get empty \AtBeginSection[]{} \AtBeginSubsection[]{} %{ % \begin{frame} % \frametitle{Plan} % \tableofcontents[currentsection] % \end{frame} %} % Change color of definiton block \AtBeginEnvironment{definition}{% \setbeamercolor{block title}{use=example text,fg=example text.fg,bg=example text.fg!20!bg} \setbeamercolor{block body}{parent=normal text,use=block title,bg=block title.bg!50!bg} } % code coloration \usepackage{listings} % L'option "[fragile]" doit être rajouté au frame pour pouvoir utiliser correctement % la police verbatim \usepackage{color} \lstset{ breaklines=true, tabsize=4, backgroundcolor=\color[RGB]{49,54,59}, basicstyle=\footnotesize\ttfamily\color{white}, commentstyle=\itshape\color[RGB]{0,136,136}, morecomment=[l]{\#}, morekeywords={*,\$,\{,\}}, stringstyle=\itshape\color[RGB]{218,116,0}, showstringspaces=false, frame=LTBR, } \lstdefinestyle{shell}{ language=bash, keywords={\$}, keywordstyle=\bfseries\color[RGB]{66,198,66} } \lstdefinelanguage{diff}{ morecomment=[f][\color{blue}]{@@}, % group identifier morecomment=[f][\color{red}]-, % deleted lines morecomment=[f][\color{green}]+, % added lines morecomment=[f][\color{magenta}]{---}, % Diff header lines (must appear after +,-) morecomment=[f][\color{magenta}]{+++}, } % Pour utiliser des colonnes \usepackage{multicol} % Pour integrer un pdf \usepackage[final]{pdfpages} % Pour les hyperliens \usepackage{hyperref} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \title[U-Boot]{UDEV \\ \textbf{Gérerer les device node}} \author[Mickaël Tansorier]{Mickaël Tansorier} \date[Août 2018]{Présentation du fonctionnement d'UDEV.} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} %\tableofcontents[subsectionstyle=hide] % ******************************* % **** PAGE DE GARDE **** % ******************************* \begin{frame} \titlepage \end{frame} % ******************************* % **** INTRODUCTION **** % ******************************* \begin{frame}{Plan} \tableofcontents[hideallsubsections] \end{frame} \section{Introduction} \subsection{device-node} \begin{frame} \texttt{UDEV} est un démon chargé de gérer les device-nodes. \begin{block}{Principe d'unix} Tout est fichier \end{block} Donc les périphériques matériels sont des pseudo-fichier.\newline Ils peuvent être manipulés par: cat, grep, open(), read(), write() etc…\newline \newline Ils sont stockés dans: \texttt{/dev} \newline On les appelle device-nodes. \end{frame} \begin{frame} \begin{list}{-}{Les device nodes sont:} \item des points d'entrée vers le noyau \item de type bloc ou char \item identifiés par un majeur et un mineur \end{list} $ $\newline Le majeur permet au noyau de savoir quel driver doit gérer le périphérique.\newline Le mineur permet au driver de savoir quel périphérique parmi ceux qu’il gère est utilisé. \end{frame} \subsection{Historique} \begin{frame}{} \begin{itemize} \item Le script \texttt{MAKEDEV} \begin{itemize} \item[-] Les majeur et mineur était codés en dur dans un script appelé par la commande mknode. \item[-] Pour créer les périphériques dans \texttt{/dev}. \item[-] Tout ceux possible existaient sur le système (\texttt{\~} 18 000) \item[-] Ne gère pas le hotplug \end{itemize} \item Le \texttt{devfs} \begin{itemize} \item[-] Les noeuds ne sont plus crées par le système mais par les drivers eux-mêmes à la détection d'un périphérique. \item[-] Mais les majeurs mineurs étaient toujours codé en dur \item[-] devfs est difficile à paramétrer \end{itemize} \item Le \texttt{udev} \begin{itemize} \item[-] udev est un programme purement user-space \item[-] udev évolue en s'appuyant sur les évolutions du noyau \item[-] Il s’appuie sur les informations laissées dans \texttt{/sys} (majeur et mineur) \item[-] Le noyau fournit un lien netlink qui permet à udev d'être prévenu lors d'un changement. \end{itemize} \end{itemize} \end{frame} % ******************************* % **** PRÉSENTATION **** % ******************************* \section{Les événements noyau} \subsection{monitor} \begin{frame}[fragile] \texttt{udev} réagit donc à des événements envoyés par le noyau via \texttt{inotify}. \begin{lstlisting}[style=shell] udevadm monitor -k \end{lstlisting} Lorsque l'on branche un USB: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] KERNEL[805.692293] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1 (usb) KERNEL[805.694999] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0 (usb) KERNEL[806.006810] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1 (net) KERNEL[806.006948] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1/queues/rx-0 (queues) KERNEL[806.007010] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1/queues/tx-0 (queues) \end{lstlisting} Et si l'on retire: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] KERNEL[800.026043] remove /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1/queues/rx-0 (queues) KERNEL[800.026228] remove /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1/queues/tx-0 (queues) KERNEL[800.026366] remove /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1 (net) KERNEL[800.050534] remove /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0 (usb) KERNEL[800.080535] remove /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1 (usb) \end{lstlisting} \end{frame} \begin{frame}[fragile] On peut demander à \texttt{udev} de nous fournir les propriétés du périphérique: \begin{lstlisting}[basicstyle=\tiny\ttfamily\color{white}] udevadm monitor -k -p \end{lstlisting} Pour une seule sortie: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] KERNEL[5763.052898] add /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1 (usb) ACTION=add BUSNUM=001 DEVNAME=/dev/bus/usb/001/003 DEVNUM=003 DEVPATH=/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1 DEVTYPE=usb_device MAJOR=189 MINOR=2 PRODUCT=bda/8153/3000 SEQNUM=1544 SUBSYSTEM=usb TYPE=0/0/0 \end{lstlisting} \end{frame} \begin{frame}[fragile] Les propriétés dépendent du type exact de périphérique mais certaines propriétés sont toujours présentes: \begin{itemize} \item \texttt{ACTION} : Le type d’événement à traiter, \item \texttt{MAJOR}, \texttt{MINOR} : Les numéro majeur et mineur du périphérique concerné, \item \texttt{SEQNUM} : un numéro croissant pour ordonner les événements, \item \texttt{SUBSYSTEM} : Le sous-système noyau ayant causé l’événement, \item \texttt{DEVPATH} : Le fichier dans \texttt{/sys} correspondant au périphérique. \end{itemize} \end{frame} % ******************************* % **** PRÉSENTATION **** % ******************************* \section{Les règles udev} \begin{frame}[fragile]{L’écriture de règles} Les règles udev peuvent venir de plusieurs endroits différents: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] /etc/udev/rules.d/ # regles locales ajoutees par l'administrateur /run/udev/rules.d/ # regles volatiles, generalement creees par d'autres regles /usr/lib/udev/rules.d/ # regles fourni par la distribution /lib/udev/rules.d/ # regles fourni par la distribution \end{lstlisting} Les fichiers sont préfixé par un numéro (comme init), et postfixé par \texttt{.rules}.\newline Exemple: \texttt{/usr/lib/udev/rules.d/82-net-usb-up.rules} \begin{lstlisting}[style=shell] ACTION=="add", RUN+="/bin/sh -c '/bin/echo %k : %p >> /root/events'" \end{lstlisting} \end{frame} \subsection{Les règles de filtrage} \begin{frame}[fragile] Pour filtrer les évènements on utilise la syntaxe: \texttt{PROPRIETE==valeur} \newline "\texttt{==}", "\texttt{!=}", "\texttt{=}", "\texttt{+=}", "\texttt{-=}", "\texttt{:=}" \newline \newline Le champs \texttt{PROPRIETE} peut prendre les valeurs suivantes: \begin{itemize} \item \texttt{ATTR\{fichier\}} — permet de filtrer sur le contenu d’un fichier dans le répertoire sysfs correspondant à l’événement en cours. \item \texttt{ATTRS\{fichier\}} — idem + également sur ceux des périphériques parents (bus, plateforme etc…). \item \texttt{ENV\{clé\}} — permet de filtrer sur une propriété ajoutée par une autre règle udev. \item \texttt{PROGRAM} — permet de filtrer sur la valeur de retour d’un programme. \end{itemize} \end{frame} \subsection{Les actions possibles} \begin{frame}[fragile] Lorsque l'on a le filtrage que l'on souhaite, on peut effectuer des actions avec les options suivantes: \begin{itemize} \item \texttt{SYMLINK} — crée un lien symbolique vers le fichier \texttt{/dev} du pérphérique. Le noyau fournit un premier fichier \texttt{/dev} dont le nom ne peut pas être changé. \item \texttt{OWNER}, \texttt{GROUP}, \texttt{MODE}, \texttt{SECLABEL\{module\}} — permet de préciser les droits d’accès et les propriétés SELinux du périphérique. \item \texttt{ATTR\{fichier\}} — permet d’écrire une valeur dans un fichier du répertoire sysfs correspondant au périphérique. \item \texttt{ENV\{clé\}} — permet de positionner un attribut interne à udev pour le périphérique en cours, \item \texttt{RUN} — permet d’exécuter un programme \end{itemize} \end{frame} \begin{frame}[fragile] Certain mots clés peuvent être utilisés pour ces actions, comme: \begin{itemize} \item \texttt{\$kernel}, \texttt{\%k} — The kernel name for this device. \item \texttt{\$devpath}, \texttt{\%p} — The devpath of the device. \end{itemize} Exemple: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] ACTION=="add", SUBSYSTEM=="net", RUN+="/bin/sh -c '/bin/echo %k : %p >> /root/events'" \end{lstlisting} Donne \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] $ cat /tmp/event usb0 : /devices/soc0/soc/2100000.aips-bus/2184000.usb/ci_hdrc.0/gadget/net/usb0 eth0 : /devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0 eth1 : /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/net/eth1 sit0 : /devices/virtual/net/sit0 lo : /devices/virtual/net/lo \end{lstlisting} \end{frame} % ******************************* % **** PRÉSENTATION **** % ******************************* \section{Analyse d'évènements} \subsection{Trouver les propriétés d'un périphérique} \begin{frame}[fragile] retrouver le répertoire sysfs d'un device: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] $ udevadm info -x -q path -n /dev/hidraw0 /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:046D:C01A.0015/hidraw/hidraw0 \end{lstlisting} Obtenir des info sur le device: \begin{lstlisting}[style=shell,basicstyle=\tiny\ttfamily\color{white}] $ udevadm info /sys/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:046D:C01A.0015/hidraw/hidraw0 P: //devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:046D:C01A.0015/hidraw/hidraw0 N: hidraw0 E: DEVNAME=/dev/hidraw0 E: DEVPATH=//devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:046D:C01A.0015/hidraw/hidraw0 E: MAJOR=247 E: MINOR=0 E: SUBSYSTEM=hidraw \end{lstlisting} \begin{itemize} \item E: une propriété purement udev. elles sont accessibles grâce à \texttt{ENV\{\}} \item N: le nom du périphérique suggéré par le noyau \item S: les liens symboliques créés vers le périphérique \item P: le chemin vers l’entrée dans \texttt{sysfs} \end{itemize} \end{frame} \subsection{Surveiller les évènements} \begin{frame}[fragile] Monitorer les actions en direct: \begin{lstlisting}[style=shell] $ udevadm monitor -p \end{lstlisting} L'option \texttt{-p} permet d'avoir les propriétés des évènements. \end{frame} \subsection{Tester des évènements} \begin{frame}[fragile] Tester un évènement: \begin{lstlisting}[style=shell] $ udevadm test -a add /sys/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:046D:C01A.0018/hidraw/hidraw0 \end{lstlisting} \end{frame} % ******************************* % **** PRÉSENTATION **** % ******************************* \section{Divers} \subsection{La règle réseau} \begin{frame}[fragile] \begin{lstlisting}[style=shell] $ cat board/eolane/modx6/rootfs_pendant/usr/lib/udev/rules.d/82-net-usb-up.rules # do not edit this file, it will be overwritten on update ACTION!="add", GOTO="net_usb_up_end" SUBSYSTEM!="net", GOTO="net_usb_up_end" ENV{ID_BUS}=="usb", RUN+="/bin/sh -c 'ifup %k'" LABEL="net_usb_up_end" \end{lstlisting} \end{frame} \subsection{mdev} \begin{frame}[fragile] \texttt{mdev} est un utilitaire similaire à \texttt{udev} présent dans \texttt{busybox}. Très utilisé dans l'embarqué.\newline \newline Mais \texttt{udev} est déjà très léger (le binaire fait 520K). \end{frame} % ******************************* % **** PRÉSENTATION **** % ******************************* \section*{Conclusion} \begin{frame} \begin{center} \begin{huge} Question ? \end{huge} \end{center} \begin{center} \textcolor{gray}{\tiny{Enfin je vais essayer de répondre...}} \end{center} $ $\newline \newline Document basé sur:\newline \url{http://www.linuxembedded.fr/2015/05/une-introduction-a-udev/} \end{frame} \end{document}