[Gllug] Re: Alcatel SpeedTouch on Slackware 10

Nix nix at esperi.org.uk
Sat Nov 19 02:09:42 UTC 2005


On Fri, 18 Nov 2005, Henry Gilbert announced authoritatively:
>                                    What I am scared of - is getting
> stuck again for days going around in loops.

If you're stuck, ask! (It seems to be working; even if people like
me are just wittering, there are many other people actually giving
you useful info :) )

>                                             All methods assumes much
> previous knowledge of things; I didn't even know about chap secrets
> and pap stuff.

Horrid PPP authentication crud of some sort, isn't it?

>                Or lib/firmware

That should come with a huge Under Construction sign on it. It works but
many of the tools to use it are embryonic to say the least. (Hence the
need for all that scripting.)

>                                .. or hotplugging ..

That's `Sticking hardware in and expecting it to work without
rebooting'. You may also encounter references to `coldplugging'; this is
`using the hotplug mechanisms to handle all hardware on the machine',
i.e. `hotplugging from a cold boot'. It allows considerable
simplification in the kernel and in early boot stages (at least it
does on distro CDs and the like which have to handle all hardware they
encounter, even pieces of hardware which conflict with each other).


With the relatively new and wonderfully flexible udev tool it's quite
simple to make devices dance to your tune whenever you plug something
in, but I'll go through all the details to make it seem more
complicated. This is probably way too detailed but I'm bored and udev
rocks; I hope this will hook more people on it. (All details based on
2.6.14. 2.4 barely supports hotplugging through a collection of horrific
hacks, and, well, if you're planning to hotplug, stay clear of it.)

(There's less insanely detailed stuff below this.)


You stick a piece of hardware in. Say a USB cable. The kernel spots the
device on the other end (assuming you built in the right drivers,
e.g. usb-storage for a hard disk), and adds nodes under /sys/class for
the new devices. e.g. when I've just plugged in a USB hard disk, I get
these new directories, and subdirectories of them:

0      /sys/devices/pci0000:00/0000:00:01.2/usb1/1-2
     ; This is the USB interface dangling off the PCI bus
0      /sys/class/usb_device/usbdev1.2
     ; This si the USB interface in a class of its own
     ; (most userspace tools, e.g. udev, use this)
0      /sys/class/scsi_device/1:0:0:0
     ; This is the SCSI device that's on the other end of the
     ; USB cable
0      /sys/class/scsi_host/host1
     ; This is the SCSI host adapter (no, it's not really a
     ; SCSI disk, but USB mass storage devices pretend to be SCSI)
0      /sys/class/scsi_generic/sg2
     ; This is the `SCSI generic' device down which interested apps
     ; (e.g. CD burners) can spray raw SCSI commands if they want.
     ; Probably this USB disk will ignore any that we choose to send,
     ; but the kernel doesn't know that so it gives us a generic
     ; device anyway.
0      /sys/block/sdb
     ; This is the block device itself, the thing at which you spray
     ; bytes to make them appear on the disk.

Now the kernel sprays messages at the udev daemon, udevd, telling it
that new hardware has turned up (it sprays more messages when hardware
gets unplugged). How it gets these messages there is in flux: in older
2.6 kernels it ran a command (`udevsend'); these days it uses the
netlink sockets, and in very recent udev releases udev uses the whizzy
new inotify mechanism to spot new nodes appearing under /sys for you.

Now there's heaps of info attached to those /sys nodes, and the
`udevinfo' command can fish it out. Say I wanted to do something when
that USB disk were plugged in: probably I'd want to make a device for it
with a fixed and descriptive name, with suitable permissions; perhaps I
might want to mount it too, or play a serenade over the speakers. Now
first I'd need a way of identifying that disk so I could tell udev to
do something with it in particular.

So I stick the archos in and find that new device node under
/sys/block. Oh look, sdb has just appeared, I wonder if that's it?

nix at loki 33 /home/nix% udevinfo -a -p /sys/block/sdb

,----
| udevinfo starts with the device the node belongs to and then walks up the
| device chain, to print for every device found, all possibly useful attributes
| in the udev key format.
| Only attributes within one device section may be used together in one rule,
| to match the device for which the node will be created.

(udevinfo says what it's for)

| device '/sys/block/sdb' has major:minor 8:16
|   looking at class device '/sys/block/sdb':
|     KERNEL=="sdb"
|     SUBSYSTEM=="block"
|     SYSFS{dev}=="8:16"
|     SYSFS{range}=="16"
|     SYSFS{removable}=="0"
|     SYSFS{size}=="39070080"
|     SYSFS{stat}=="      83      411     2825     4490        0        0        0        0        0     4490     4490"

This is the block device. *Every one* of the lines above with equals
signs in it can be used to identify the device to udev. I can't imagine
why you'd want to use that stat field --- I'm not even sure what the
figures mean in this case --- but you could if you wanted to.

udevinfo spots that this device is a fiction invented by the kernel to
correspond to a slice of a real physical piece of hardware. So it gives
you some info on that:

| follow the "device"-link to the physical device:
|   looking at the device chain at '/sys/devices/pci0000:00/0000:00:01.2/usb1/1-2/1-2:2.0/host2/target2:0:0/2:0:0:0':
|     BUS=="scsi"
|     ID=="2:0:0:0"
|     DRIVER=="sd"
|     SYSFS{device_blocked}=="0"
|     SYSFS{iocounterbits}=="32"
|     SYSFS{iodone_cnt}=="0x58"
|     SYSFS{ioerr_cnt}=="0x0"
|     SYSFS{iorequest_cnt}=="0x58"
|     SYSFS{max_sectors}=="240"
|     SYSFS{model}=="DK23DA-20       "
|     SYSFS{queue_depth}=="1"
|     SYSFS{queue_type}=="none"
|     SYSFS{rev}=="00J2"
|     SYSFS{scsi_level}=="3"
|     SYSFS{state}=="running"
|     SYSFS{timeout}=="30"
|     SYSFS{type}=="0"
|     SYSFS{vendor}=="HITACHI_"

(This is the disk itself, on the other end of that USB cable, a 20Gb
Hitachi disk.)

It walks up the tree, looking at the device that this disk is part of.

|   looking at the device chain at '/sys/devices/pci0000:00/0000:00:01.2/usb1/1-2/1-2:2.0/host2/target2:0:0':
|     BUS==""
|     ID=="target2:0:0"
|     DRIVER=="unknown"
|
|   looking at the device chain at '/sys/devices/pci0000:00/0000:00:01.2/usb1/1-2/1-2:2.0/host2':
|     BUS==""
|     ID=="host2"
|     DRIVER=="unknown"
|
|   looking at the device chain at '/sys/devices/pci0000:00/0000:00:01.2/usb1/1-2/1-2:2.0':
|     BUS=="usb"
|     ID=="1-2:2.0"
|     DRIVER=="usb-storage"
|     SYSFS{bAlternateSetting}==" 0"
|     SYSFS{bInterfaceClass}=="08"
|     SYSFS{bInterfaceNumber}=="00"
|     SYSFS{bInterfaceProtocol}=="50"
|     SYSFS{bInterfaceSubClass}=="06"
|     SYSFS{bNumEndpoints}=="03"
|     SYSFS{modalias}=="usb:v05ABp0060d1101dc00dsc00dp00ic08isc06ip50"

Here we have several layers of weird abstractions corresponding to who
knows what hardware inside the MP3 player at the other end of the hard
disk. The nice thing about udev is that if you don't know what one of
these things is you can just ignore it.

Still further up, and we strike gold:

|   looking at the device chain at '/sys/devices/pci0000:00/0000:00:01.2/usb1/1-2':
|     BUS=="usb"
|     ID=="1-2"
|     DRIVER=="usb"
|     SYSFS{bConfigurationValue}=="2"
|     SYSFS{bDeviceClass}=="00"
|     SYSFS{bDeviceProtocol}=="00"
|     SYSFS{bDeviceSubClass}=="00"
|     SYSFS{bMaxPacketSize0}=="64"
|     SYSFS{bMaxPower}==" 98mA"
|     SYSFS{bNumConfigurations}=="1"
|     SYSFS{bNumInterfaces}==" 1"
|     SYSFS{bcdDevice}=="1101"
|     SYSFS{bmAttributes}=="c0"
|     SYSFS{configuration}==""
|     SYSFS{devnum}=="3"
|     SYSFS{idProduct}=="0060"
|     SYSFS{idVendor}=="05ab"
|     SYSFS{manufacturer}=="ARCHOS          "
|     SYSFS{maxchild}=="0"
|     SYSFS{product}=="ARCHOS USB2.0 _P4a_"
|     SYSFS{serial}=="wwww.archos.comA"
|     SYSFS{speed}=="12"
|     SYSFS{version}==" 2.00"

This is the thing plugged in at the other end of the USB cable. The
manufacturer and product keys in particular look useful, as long as we
don't have several things made by Archos, and if we do the idProduct key
will be useful too. (The serial number is... amusingly stupid.)  [...]
`----

Now we can teach udev to mount them. So in a new file in
/etc/udev.d/rules.d (existing ones are apt to be overwritten by
your distribution's package manager), I paste in a few useful-
looking keys from the mass udevinfo printed, and a few `actions'
from the udev manpage:

KERNEL=="sd*1", SYSFS{product}=="ARCHOS*", SYMLINK="archos", GROUP="mp3", MODE="0660"

That's it: with that one line in there we'll get an `archos' symlink to
the first partition on whatever SCSI disk gets plugged in, as long as
it's an Archos disk; it'll get its group and mode fiddled too so mere
users in the right group can mount them. When the device is removed,
udev automatically reverts all of this.

This is a tiny fraction of udev's power, though. there's a RUN action
that lets you run arbitrary shell scripts to suck any sort of info you
like out of the device or manipulate it in whatever way you want.  One
of Greg K-H's first examples was a short script which looked up an
inserted audio CD on the CDDB database and created devices corresponding
to its audio tracks!

This is astonishingly flexible. I don't think I've ever seen any other
OS giving you anything like this much control over what happens when
you plug things in and unplug them again.

Linux had sucky hotplugging support for years... but no more. Oh no.

>                                                     User Space /
> Kernel Space are concepts that fills my being with dread.

`Userspace' is the place programs mortals write run in. They have strict
permissions controls enforced by the kernel, and can be stopped at any
time by it (and indeed are, very frequently). Much of the `look' of the
non-graphical parts of userspace is standardized by POSIX, and in
general the userspaces of different Unixes look pretty much alike
(ignoring weird-ass alien invaders like HP-UX and AIX).

A running Unix box is the ultimate police state. Programs running in
userspace can do very little on their own. Just about all they can do is
raw computation, actually: if they want to do file I/O, or communicate
with anything, or, hell, even exit, they have to call one of a variety
of functions --- mostly standardized by POSIX --- which end up, after
many adventures, calling into the kernel. These act as gatekeepers
and policemen, ensuring that you don't interfere with anyone else
and that you don't do anything you're not allowed to do.

Now on Unix platforms the kernel is a rather peculiar thing. On many
other OSes the kernel is this great big thing almost like another
process, and only one process can ask the kernel to do anything at once:
but on Unix systems (and on Windows too, in fact), the kernel, while
it's still a single piece of code, when running is a sort of parasitic
entity attaching itself remora-like to every process in the system. The
kernel has complete control over every aspect of the system and every
detail of its function, but it does *nothing* on its own: it only does
things when it's asked to, either by an external interrupt like an
incoming network packet or (more often) by a user process asking it to
do something by making a system call (or `syscall').

What happens when a user process asks is a sort of magic trick. In the
process of asking, the user process sheds its limited, restricted
userspace mask, starts executing kernel code, and gains all the infinite
powers and capabilities of the kernel. As long as it's there, it's known
as being `in kernelspace' or `in kernel mode', and CPU time it consumes
is counted against `system time' in tools such as top. Several processes
can be doing this at once without incident (that's one of the things
those low-latency patches encourage). When its job is done, the kernel
returns (a pretty normal function call return), and the cloak of
userspace descends around it once more, barring it from doing pretty
much everything --- until it makes its next syscall.

(OK, so the kernel's powers aren't actually *infinite*, or I'd have
asked my Linux box for mastery of all the world and a pile of gold as
high as the London Eye. But it can do anything with your machine that
it desires, so compared to ordinary userspace processes it's a god.

Note that the kernel knows damn well that it's running on behalf of an
ordinary user, and checks to make sure you're not asking it to do
something you should be forbidden to do: indeed, this is the *only
place* where permissions checks and things can safely be done, because
the possibibly malicious user code can't interfere with it: the user
code can do hardly anything. It has to ask the kernel for permission
before it's even allowed to modify itself, and it's certainly not going
to be allowed to modify anything as important as the kernel.)

Most processes that aren't compute hogs spend almost their *entire time*
inside the kernel, and nearly all that time asleep or waiting for some
slow hardware device like a disk or the network. The *only* way a
process can go to sleep --- as opposed to tightly looping doing nothing,
which is considered rude and which the kernel penalizes heavily --- is
to ask the kernel to sleep on its behalf. You can see what processes are
doing by looking at the `stat' field in ps, as in this:

% ps -eo pid,user,stat,wchan,args

The valid stat values are presently (from fs/proc/array.c):

	"R (running)",
	"S (sleeping)",
	"D (disk sleep)",
	"T (stopped)",
	"T (tracing stop)",
	"Z (zombie)",
	"X (dead)"

Now one notable thing is that *only* processes in R state are in
userspace at any one time (and only some of them). Most of them are S,
sleeping in the kernel; only a few will ever be in any other status;
processes marked D are in the kernel doing something so important that
they can't be interrupted, and processes marked Z and X don't exist at
all (in fact, if you see an X, it's a kernel bug!)

(You can even see what kernel function some of those processes are
executing; that's the wchan field.)

Er. I hope that made it a bit clearer, anyway.

> .. I am all up for it. What I can't do is fill in any gaps - - I mean
> I could try and destroy everything :)

That's a good idea if you're learning. I wrote off several test
installations just trying to find good ways to manage things :)

-- 
`Y'know, London's nice at this time of year. If you like your cities
 freezing cold and full of surly gits.' --- David Damerell

-- 
Gllug mailing list  -  Gllug at gllug.org.uk
http://lists.gllug.org.uk/mailman/listinfo/gllug




More information about the GLLUG mailing list