Can someone illustrate what's linux device number's minor number exactly for? - linux

The minor number is used by the kernel
to determine exactly which device is
being referred to.
The above explanation is just two abstract, can someone illustrate?

The major number identifies the device driver to use, the minor number indicates which device. If you have multiple partitions, for instance, each gets its own minor:
brw-rw---- 1 root disk 8, 0 Jun 3 20:48 /dev/sda
brw-rw---- 1 root disk 8, 1 Jun 3 20:48 /dev/sda1
brw-rw---- 1 root disk 8, 2 Jun 3 20:48 /dev/sda2
Minor 0 in this case is the raw drive, minor 1 is partition 1, minor 2 is partition 2, etc. Not all devices use 0 as a special case, however. The serial devices start their numbering at 0, where /dev/tty0 is just the first (virtual) terminal device on the system:
crw--w---- 1 root tty 4, 0 Jun 3 20:48 /dev/tty0
crw------- 1 root root 4, 1 Jun 3 20:50 /dev/tty1
crw------- 1 root root 4, 2 Jun 3 20:50 /dev/tty2
crw------- 1 root root 4, 3 Jun 3 20:50 /dev/tty3
In either event, when the device file is opened the kernel will use the major number to determine which module will handle the file and passes the minor to the open() method of the struct file_operations structure that was registered with register_chrdev().

as in the language C ,counting starts from 0 ...it could be a sort of convention followed by driver writers ...after all everything in Linux is based upon C or to some extent C++.Its just a numbering scheme ..You can also start naming your devices from any number between 0 and 255,but please be carefull do not cross the 255 mark for minor numbers else you may overwrite the next available major number..hope this answer helps

Related

linux kernel: regulator consumer usage from userspace

I have some kind of driver in user space:
program talk via some interface(rs232) with device.
Also I have pin(gpio) to switch on/off this device.
I do not code in my program concrete gpio, to make it more portable,
so I modify device tree description of my board,
and describe regulator-fixed, after that I thought to use
userspace-consumer driver to control power on/off,
but looks like that not kernel developers expected
(link to discussion of similar problem, not my):
http://patchwork.ozlabs.org/patch/374912/
So how should I control switch on/off
of my device from user space without adding to my program
information about what conrete gpio used to switch on/off device?
More details:
In my board dts I described my pin like this:
regulator-deviceX {
status = "okay";
compatible = "regulator-fixed";
regulator-name = "DEV_X_ON#";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio5 4 GPIO_ACTIVE_LOW>;
};
And of course, after boot "gpio = <&gpio5 4 GPIO_ACTIVE_LOW>" was
locked by the kernel, and it is impossible to use it via /sys/class/gpio interface.
Bad think about such approach, that is impossible (or I don't see how) to
change regulator state from user space, as you can see "state" is read only file.
root#board:/sys/class/regulator/regulator.1# ls -l
lrwxrwxrwx 1 root root 0 May 3 03:32 device -> ../../../regulator-deviceX
-r--r--r-- 1 root root 4096 May 3 03:32 microvolts
-r--r--r-- 1 root root 4096 May 3 03:32 name
-r--r--r-- 1 root root 4096 May 3 03:32 num_users
drwxr-xr-x 2 root root 0 May 3 03:32 power
-r--r--r-- 1 root root 4096 May 3 03:32 state
lrwxrwxrwx 1 root root 0 May 3 03:25 subsystem -> ../../../../class/regulator
-r--r--r-- 1 root root 4096 May 3 03:32 suspend_disk_state
-r--r--r-- 1 root root 4096 May 3 03:32 suspend_mem_state
-r--r--r-- 1 root root 4096 May 3 03:32 suspend_standby_state
-r--r--r-- 1 root root 4096 May 3 03:32 type
-rw-r--r-- 1 root root 4096 May 3 03:25 uevent
So, the final solution looks like this:
Step 1
Describe device in device tree, though you no need
kernel for handling it, but looks right to describe it here
gps-reciever {
compatible = "my_company_name,gps_recv_name";
vcc-supply = <&ext_gps_recv_reg>;
comment = "connected via usb<->rs232, port0";
};
where ext_gps_recv_reg of any normal regulator.
Step 2
I wrote a simple platform device driver for linux kernel,
that compatible with device above, and in probe function of this
driver I call platform_device_register_full that setup arguments for
userspace_consumer driver.
After that I can find suitable file via name:
cat /sys/bus/platform/devices/reg-userspace-consumer*/name,
and then disable/enable regulator via:
echo "disabled" > /sys/bus/platform/devices/reg-userspace-consumer*/state
So I separate device description from linux kernel implementation.

Some high level questions about how PAM is designed

I'm creating a PAM module for a project. The PAM module will be using a library that will be re-used by some command line utilities (rather than re-writing everything each time). In this library, I want to have it interpret policy that discriminate against and/or logs according to subnet memberships of the remote host. Near as I can tell this value is probably coming from the authenticating application, but I don't know. Since the shared object won't have access to the pamh structure from libpam I can't just do a pam_get_item (like I would be able to from the PAM module itself) so I've had to resort to other means.
The best solution I've come up with is to have the shared object look for a connected TTY, if it's there go to utmp and find the login process associated with that TTY, extract the IP address from there. If there isn't a TTY, assume it's an initial login of a network user. The library then iterates over the sockets (which I've defined as basically any symlink with the word "socket" in the target's filename when you do a ls -l /proc/<pid>/fd) and uses the socket inode number to cross reference with /proc/net/tcp and extracts the remote IP address associated with that inode number. If it doesn't find an inode there then it assumes it's Unix domain or tcp6 (IPv6 support in this is forthcoming and not terribly important for the near future). If it still isn't able to find it, assume that some daemon has called an application linking against it and interpret it as such (might do something eventually, if it's worthwhile, but for now it's just a big NOOP if the first two don't return anything.
It seems to work but I have some high level questions about how PAM is supposed to work:
Is there some official standard that governs PAM operation? For example, is it covered by a POSIX standard somewhere? I know there are multiple PAM implementations (four or five that I've found thusfar) but I don't know if existing commonalities are de jure or de facto or just how I happen to have my system configured.
After I did a ls -l /proc/<pid>/fd > /lsOutput from the module itself (via system()):
[root#hypervisor pam]# cat /lsOutput total 0
lrwx------. 1 root root 64 Jun 15 15:09 0 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:09 1 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:09 2 -> /dev/null
lr-x------. 1 root root 64 Jun 15 15:09 3 -> socket:[426180]
[root#hypervisor pam]#
And issuing a manual ls after the user logins in:
[root#hypervisor pam]# ls -l /proc/18261/fd
total 0
lrwx------. 1 root root 64 Jun 15 15:15 0 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 1 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 11 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 12 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 13 -> socket:[426780]
lrwx------. 1 root root 64 Jun 15 15:15 14 -> socket:[426829]
lrwx------. 1 root root 64 Jun 15 15:15 2 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 3 -> socket:[426180]
lrwx------. 1 root root 64 Jun 15 15:15 4 -> socket:[426322]
lr-x------. 1 root root 64 Jun 15 15:15 5 -> pipe:[426336]
l-wx------. 1 root root 64 Jun 15 15:15 6 -> pipe:[426336]
lrwx------. 1 root root 64 Jun 15 15:15 7 -> socket:[426348]
lrwx------. 1 root root 64 Jun 15 15:15 8 -> socket:[426349]
lrwx------. 1 root root 64 Jun 15 15:15 9 -> /dev/ptmx
[root#hypervisor pam]#
So basically, it seems like both the TTY and any additional sockets get opened only AFTER the session modules finish (my temporary test module's session handling is the last in the stack for the sshd service). I've been unable to get it to be otherwise (or even think of a time when the connecting client won't be a TCP socket at descriptor 3).
Is this just due to my lack of imagination or is it necessarily so? I'm leaning towards the latter as it would seem that communicating with the client would be a pre-requisite to doing pretty much anything else that's useful. I don't know that for sure, so I feel I should ask somebody. Will descriptor 3 always be the authenticating client (my .so only makes the assumption that it's the lowest numbered TCP socket, and only if there's no TTY, but it seems like 3 should always be the descriptor for the connecting client). Would pulling the first TCP descriptor be a "deterministic" way of establishing the remote client's identity? Or is there no prescribed way this is supposed to play out and that's just how either my system is configured or how SSH has chosen to interface with PAM?
Is it sshd that's setting the rhost value or is that coming from some place else? I've tried grep-ing over the source code for both SSH and libpam, but no dice. I can see where libpam handles the setting of the host value when something call pam_set_item, but not were pam_set_item actually gets called to set it to be this or that particular host.
Any amount of help would be appreciated, I've googled but I'm starting to get splinters on my fingertips from scraping the bottom of the barrel.
Main reason I'm interested in knowing this is so that I'll end up not only with the "right" answer but mostly so that I won't have any surprises later on down the road. We have some Solaris platforms we may do this on, but my main motivation is to have assumptions that are grounded in things that are actually going to be constant.
I also realize that I could have the client programs/modules feed the host information to the library, but that would likely involve code re-write two or three times (as the CLI tools prepare session information from utmp and the PAM module from pam_get_item) and potentially make the project look more complex than it really needs to be.
Answering some of your questions:
"Is there some official standard that governs PAM operation?"
Apparently, yes. Wikipedia's entry on Pluggable_Authentication_Modulesays "PAM was standardized as part of the X/Open UNIX standardization process, resulting in the X/Open Single Sign-on (XSSO) standard." I have never found this particularly relevant to my dealings with it.
"Is this just due to my lack of imagination or is it necessarily so?"
<magicEightBall>"Concentrate and ask again"</magicEightBall> (It's ambiguous which "this" is being referred to - perhaps you can clarify?
"Will descriptor 3 always be the authenticating client?"
This is a behaviour of the application, rather than PAM.
Would pulling the first TCP descriptor be a "deterministic" way of establishing the remote client's identity?
Also a behaviour of the application.
"Is it sshd that's setting the rhost value or is that coming from some place else?"
It is sshd that sets the rhost value. In openssh's file auth-pam.c, function sshpam_init(), you'll find:
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
Some general notes:
rather than keying off the TTY - which, as you've discovered get set later - you can walk the process lineage via getppid() and /proc.
don't trust system() in PAM modules - it uses a user's environment, and may not be the one you expect. Use fork()/execlp() instead.

Device node at /dev/tty* not getting created for uart serial driver

I have written a simple UART serial driver in embedded Linux running busybox with mdev rules. I have provided .dev_name as "ttyC2C" in my driver code.
static struct uart_driver serial_omap_reg = {
.owner = THIS_MODULE,
.driver_name = "Omap-C2C-Serial",
.dev_name = "ttyC2C",
.nr = OMAP_MAX_HSUART_PORTS,
.cons = NULL,
};
However the node is getting created in
./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
./sys/class/tty/ttyC2C0
/ # ls -l ./sys/class/tty/ttyC2C0
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 ./sys/class/tty/ttyC2C0 -> ../../devices/platform/omap_c2c_uart.0/tty/ttyC2C0
/ # ls -l ./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
-r--r--r-- 1 root 0 4096 Jan 1 00:14 dev
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 device -> ../../../omap_c2c_uart.0
drwxr-xr-x 2 root 0 0 Jan 1 00:14 power
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 subsystem -> ../../../../../class/tty
-rw-r--r-- 1 root 0 4096 Jan 1 00:14 uevent
/ #
The mdev rules for tty are:
tty 0:5 0666
tty.* 0:0 0620
How to get device node as /dev/ttyC2C ?
You are confusing two things. The sysfs nodes you are seeing are indeed maintained by the kernel based on the kobject hierarchy. However device nodes are entirely a user space problem and can exist anywhere (although by convention are under /dev).
So by hand you would first find the major:minor numbers:
cat /sys/class/tty/ttyC2C0/dev
And then:
mknod /dev/ttyC2C0 c ${MAJOR} ${MINOR}
However as you have already indicated you are using the fork of udev, mdev to handle the user space creation of device nodes. However the matching rules look odd to me. I assume mdev has the equivalent of udevadm which should help you write the matching rules. For example my USB tty driver can be queried like this:
udevadm info -a -p /sys/class/tty/ttyUSB0
And looking at the tree produced I can see a list of udev attributes which I could use to match. So in my case:
KERNEL=="ttyUSB0", DRIVERS=="ftdi_sio", NAME="ttyUSB0"
Would be enough to match (although my distro has a lot more complex matching rules to deal with dynamic setups).
I'm guessing but I suspect the mapping rule you want would look more like:
KERNEL=="ttyC2C", NAME="ttyC2C"
Although you might need a bit more to ensure you get device nodes created for each port (minor number?).
Does adding a specific mdev rule to your /etc/mdev.conf for ttyC2C resolve your problem ?
Something like one of the following ?
ttyC2C[0-9]+ root:tty 620
or
ttyC2C[0-9]+ root:tty 620 #/bin/ln -sf $MDEV ttyC2C

Linux Userspace GPIO Interrupts using sysfs

I would like to use interrupts with GPIO on userspace using sysfs.
I use these commands :
[root#at91]:gpio109 > echo 109 > export
[root#at91]:gpio109 > cd gpio109/
[root#at91]:gpio109 > ll
-rw-r--r-- 1 root 0 4096 Jan 1 00:17 direction
drwxr-xr-x 2 root 0 0 Jan 1 00:17 power
lrwxrwxrwx 1 root 0 0 Jan 1 00:17 subsystem -> ../../gpio
-rw-r--r-- 1 root 0 4096 Jan 1 00:17 uevent
-rw-r--r-- 1 root 0 4096 Jan 1 00:17 value
The gpio works well but I can't use interrupts.
I read everywhere i must have an edge file to poll this file. But on my system this file doesn't exist.
I made a lot of tries to find a solution but remain unsuccessfull.
My target is an AT91SAM9263 on linux kernel 2.6.30.
At the boot of my board I got this message on interrupts :
AT91: 160 gpio irqs in 5 banks
which show that the function at91_gpio_irq_setup() is well executed.
Have you any idea ?
The "edge" file only exists if that GPIO pin can be configured as a an interrupt generting pin. See: http://www.mjmwired.net/kernel/Documentation/gpio.txt#634.
Since you don't see it, it means the driver and possibly the hardware do not support using that GPIO pin for interrupt source.

knowing a device special file major and minor numbers in linux

All files in /dev are special files... they represent devices of the computer.
They were created with the mknod syscall. My question is: How can I know the minor and
major numbers that were used to create this special file?
The list is called the LANANA Linux Device List, and it is administered by Alan Cox.
You can find the latest copy online (direct link), or in the Linux source. Its filename in the kernel tree is Documentation/devices.txt.
To see the major and minor numbers that created a node in /dev (or any device node for that matter), simply use ls with the -l option:
22:26 jsmith#undertow% ls -l /dev/xvd?
brw-rw---- 1 root disk 202, 0 Nov 1 20:31 /dev/xvda
brw-rw---- 1 root disk 202, 16 Nov 1 20:31 /dev/xvdb
brw-rw---- 1 root disk 202, 32 Nov 1 20:31 /dev/xvdc
In this example, 202 is the three devices' major number, and 0, 16, and 32 are minors. The b at left indicates that the node is a block device. The alternative is c, a character device:
crw-rw-rw- 1 root tty 5, 0 Nov 22 00:29 /dev/tty
$ ls -l /dev/fd0 /dev/null
brw-rw---- 1 root floppy 2, 0 Nov 22 19:48 /dev/fd0
crw-rw-rw- 1 root root 1, 3 Nov 22 19:48 /dev/null
$ stat -c '%n: %F, major %t minor %T' /dev/fd0 /dev/null
/dev/fd0: block special file, major 2 minor 0
/dev/null: character special file, major 1 minor 3
Most device numbers are fixed (i.e. /dev/null will always be character device 1:3) but on Linux, some are dynamically allocated.
$ cat /proc/devices
Character devices:
...
10 misc
...
Block devices:
...
253 mdp
254 device-mapper
$ cat /proc/misc
...
57 device-mapper
...
For example, on this system, it just so happens that /dev/mapper/control will be c:10:57 while the rest of /dev/mapper/* will be b:254:*, and this could differ from one boot cycle to another -- or even as modules are loaded/unloaded and devices are added/removed.
You can explore these device registrations further in /sys.
$ readlink /sys/dev/block/2:0
../../devices/platform/floppy.0/block/fd0
$ cat /sys/devices/platform/floppy.0/block/fd0/dev
2:0
$ readlink /sys/dev/char/1:3
../../devices/virtual/mem/null
$ cat /sys/devices/virtual/mem/null/dev
1:3
You can also use stat.
$ stat -c 'major: %t minor: %T' <file>
Especially for block devices:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 90G 0 disk
├─sda1 8:1 0 4G 0 part [SWAP]
├─sda2 8:2 0 4G 0 part /
Alternative that doesn't depend on stat:
$ cat /sys/class/*/random/dev
1:8

Resources