Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
How does the kernel know how to handle read() of a reg-file file differently than read() block-device file ?
I know it was mentioned that inode makes no diff, but is that true? How would kernel know the diff between reg-file or block-device if kernel does not read the info in the inode? open() must invoke kernel to read the inode data, no?
The block device has an inode in the /dev directory identifying it as "block special file". That, plus the major device number, tells the kernel what driver to use to access the device. It's that driver that accepts read and write requests like you would use on an ordinary file, as well as seek and various ioctl operations that are peculiar to block devices.
Inodes in /dev are, in modern systems, populated at boot time and when new devices are connected. You can run a command like "stat /dev/sda" to see much of the content of those inodes.
How does the kernel know how to handle read() of a reg-file file differently than read() block-device file ?
It will even handle the case when the file is accessible over network or on tape or CD or whatever.
when you call open, kernel will look for the given path and will assign the "responsible" device driver to that and store it next to the file descriptor. Reading the fd means calling the read function of the given device driver.
It will even handle the case when the file is accessible over network or on tape or CD or whatever.
when you call open, kernel will look for the given path and will assign the "responsible" device driver to that and store it next to the file descriptor. Reading the fd means calling the read function of the given device driver.
I get open(), fd, functions read() write() etc on the fd.
When the open() on block device hits kernel, is there a file map for the special files (/dev/*), etc ?
How does read() know that the open(file) is a block device and the start of that special "file" is block-0 and ends at block-1728729390, and then should read the blocks sequentially? We know 100% that the inode has to be read, because all commands do (or should) check file perms, etc.
Last edited by Linux_Kidd; 02-29-2024 at 10:32 AM.
The read() and write() system calls do not examine the inode. It is the open() system call that reads the directory entry for the path you gave (e.g., "/dev/sda"). That directory entry maps that name to an inode number. The kernel reads that inode from the /dev filesystem, checks that the permissions allow the requested access, sees that the file type is "block special", and uses the major device number to map all future I/O calls to the proper driver for that device. The read() and write() calls neither know nor care what the device type is. They just pass the requests to the device driver, which knows how the device is accessed.
Again, open returns a file descriptor. This call (open) is already part of the system, see man page:
Quote:
The open() system call opens the file specified by pathname. ...
The return value of open() is a file descriptor, a small,
nonnegative integer that is an index to an entry in the process's
table of open file descriptors. The file descriptor is used in
subsequent system calls (read(2), write(2), lseek(2), fcntl(2),
etc.) to refer to the open file.
The first parameter is the file descriptor, and based on the file descriptor the system will find the correct read/write/whatever function which can perfectly manage the given path.
The first parameter is the file descriptor, and based on the file descriptor the system will find the correct read/write/whatever function which can perfectly manage the given path.
You can't get an fd entry without 1st reading inode info.
And if the system (kernel) needs to find the right functions to use on the fd, does if have different functions if the "file" is a block device vs reg file?
If there are different functions based on file type, how does it know the file type?
You can't get an fd entry without 1st reading inode info.
And, the open() call reads the inode.
Quote:
And if the system (kernel) needs to find the right functions to use on the fd, does if have different functions if the "file" is a block device vs reg file?
If there are different functions based on file type, how does it know the file type?
This is all information retrieved fom the inode. "Device type: 8,0" shows the major and minor device numbers, which identify the driver (8 = disk driver) and which particular device (2 = the second partition of the first disk).
This is all information retrieved fom the inode. "Device type: 8,0" shows the major and minor device numbers, which identify the driver (8 = disk driver) and which particular device (2 = the second partition of the first disk).
I totally get all this.
A read() of the fd that's created from open(), has to be different somewhere depending on file type.
The kernel-driver to hardware when a read() is done must be different for file type reg-file vs block-device. A file can/will be fragmented all over the disk, whereas there is no such concept of fragmentation for a block device, which for a harddisk it only has a start and ending block number.
The sda2 is 660 root:disk , when non-root Jim runs 'cp' on a file, is there some form of impersonation going on to be able to read() a file that is in sda2 ?
Yes, there must be a link between the fd (file descriptor) and the driver in charge: either the device driver or the fs (file system) driver (or the pipe driver or the socket driver ...).
And a "mount" creates something with a link between fs driver and device driver.
Last edited by MadeInGermany; 03-01-2024 at 12:52 AM.
A read() of the fd that's created from open(), has to be different somewhere depending on file type.
The kernel-driver to hardware when a read() is done must be different for file type reg-file vs block-device. A file can/will be fragmented all over the disk, whereas there is no such concept of fragmentation for a block device, which for a harddisk it only has a start and ending block number.
The sda2 is 660 root:disk , when non-root Jim runs 'cp' on a file, is there some form of impersonation going on to be able to read() a file that is in sda2 ?
That's what I explained already. During open the kernel identifies the type of the target, and it creates an entry in the process's table of open file descriptors. The file descriptor is used in subsequent system calls (read(2), write(2), lseek(2), fcntl(2), etc.) to refer to the open file.
Why don't you read the official documentation?
Also during open the kernel checks the permissions, if the given process has access right to the given resource. If not it won't be opened at all and there will be no file descriptor created. Additionally read will not be invoked at all, because without fd it is just pointless.
Quote:
You can't get an fd entry without 1st reading inode info.
That is just wrong. You can get fd entry even if there is no inode at all. If you open a regular file that inode will be "collected" and used later in other calls. But for example if you open a block/raw device, a port or anything on a remote / virtual filesystem [probably] there will be no inode to use.
open() takes a pathname, and a pathname is a directory entry, and a directory entry links to an inode, and the inode is checked for access, and finally the open() returns an fd.
So yes, at least for open(),
Quote:
You can't get an fd entry without 1st reading inode info.
a path on a real filesystem links to an inode, but a path to your camera, mouse, mic or whatever cannot be linked to that. But probably it can be emulated somehow.
Additionally an inode of a file on a remote filesystem is useless, that works differently.
Permissions are specified on directory level (not to speak about acl), which are all stored outside of that inode.
Inode may contain user/group information but you can open files on filesystems which do not have permission related attributes (or even inodes), like fat.
I think a FAT driver must provide fake-inodes, to be compatible with Unix/Linux.
I don't have a FAT fs at hand - test it yourself, run
ls -li on a mounted FAT fs.
Last edited by MadeInGermany; 03-01-2024 at 06:26 AM.
That's what I explained already. During open the kernel identifies the type of the target, and it creates an entry in the process's table of open file descriptors. The file descriptor is used in subsequent system calls (read(2), write(2), lseek(2), fcntl(2), etc.) to refer to the open file.
Why don't you read the official documentation?
Also during open the kernel checks the permissions, if the given process has access right to the given resource. If not it won't be opened at all and there will be no file descriptor created. Additionally read will not be invoked at all, because without fd it is just pointless.
That is just wrong. You can get fd entry even if there is no inode at all. If you open a regular file that inode will be "collected" and used later in other calls. But for example if you open a block/raw device, a port or anything on a remote / virtual filesystem [probably] there will be no inode to use.
Doesn't every file have an inode in linux? When does a file not have an inode?
This cli is from one on my VM's. Device type "fd"?
Also, perms 0660 root:disk, so my user Jimmy should not be able to 'cp /dev/dm-0 $HOME/steal/disk.img' , but how does Jimmy do 'cp $HOME/yankees.jpg $HOME/bkup/' (the filesystem is all on dm-0). Does 'cp' inherit a permission?
no, cp does not inherit permissions, it works differently.
cp needs $HOME/yankees.jpg, and kernel will check the device (where is it mounted), look for device driver, checks permissions (of the named file), and creates the file descriptor. cp itself will not directly read /dev/dm-0, but will call the read method of the given file descriptor (if there was permission to read that file) and kernel (together with the device driver) will look for track/sector/whatever information needed, retrieves the required data from the block device and returns to the cp as the content of the file.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.