简体   繁体   中英

How can I get the devnode of a device using its file descriptor

For example I opened up 2 devices in an array of devices..

NODES are /dev/ttyUSB0, /dev/ttyUSB1 etc..

#define MAXDEV 4
devlist[MAXDEV];
const char *devices[] = {"/dev/ttyUSB0","/dev/ttyUSB1");


for(loop =0; loop<sizeof(devices); loop++){

    fd= open(devices[loop]);

}

Now I add them to the list of fds;

for(i=0; i<MAXDEV; i++){

if(devlist[i] != 0){
devlist[i] = fd;
fd = -1;
}

}

Now I read on the devices for data.

    for(iter=0; iter<MAXDEV; iter++){

if(FD_ISSET(devlist[iter],&fds)){

if ((nbytes = read(devlist[iter], buf, sizeof(buf)-1)) > 0 && nbytes != 0)
                    {

                 buf[nbytes] = '\0';

                     printf("Data Received on Node ???");

                    }
                if(nbytes < 0){
                            printf("connection reset\n");
                            FD_CLR(devlist[iter], &fds);
                            close(devlist[iter]);
                            devlist[iter] = 0;

                        }
                        if(nbytes ==0){
                            printf("Device Removed on Node ???\n");


                        FD_CLR(devlist[iter], &fds);
                            close(devlist[iter]);
                            devlist[iter] = 0;

                        }
    }
}

Now how do I get the device node using its fd?.. Thanks.

The proper way to do this is to do your own book-keeping. That would allow you to log the device node name exactly as supplied by the user, rather than provide an equivalent, yet confusingly different one.

For example you could use a hash table , to associate file descriptor numbers to char arrays with the device name used for the corresponding open() call.

A simpler, but far more fragile and definitely not recommended, solution might involve using a simple array of pointers to char with an inordinately large size, in the hopes that any file descriptor value that you may encounter can be used as an index to the appropriate string without going beyond the array bounds. This is slightly easier to code than a hash table, but it will cause your program to die horribly if a file descriptor value exceeds the maximum allowed index in your string array.

If your program is bound to the Linux platform anyway, you might be able to, uh, cheat by using the /dev/fd directory or the /proc filesystem (more specifically the /proc/self/fd directory to which /dev/fd is usually a symbolic link). Both contain symbolic links that associate file descriptor values to canonical versions of the paths that where used to open the corresponding files. For example consider the following transcript:

$ ls -l /proc/self/fd
total 0
lrwx------ 1 user user 64 Nov  9 23:21 0 -> /dev/pts/10
l-wx------ 1 user user 64 Nov  9 23:21 1 -> /dev/pts/10
lrwx------ 1 user user 64 Nov  9 23:21 2 -> /dev/pts/10
lr-x------ 1 user user 64 Nov  9 23:21 3 -> /proc/16437/fd/

You can use the readlink() system call to retrieve the target of the link that corresponds to a file descriptor of interest.

You need the fstat(2) syscall, perhaps also fstatfs(2) . Check that it succeeded.

  struct stat st;
  memset (&st, 0, sizeof(st));
  if (fstat (fd, &st))
    perror("fstat");
  else {
    // use st, notably st.st_rdev
  }

Remember that you could have a device outside of /dev . If you are sure that your device is in it, you could stat(2) every entry in it, and compare their st_rdev

Read also Advanced Linux Programming (it is online under a free license, but you may want to buy the book).

Well I can see this question is about 1 year old. But right now I was looking for a way of doing this. And I found it. For getting the device node using the file descritor you can combine stat and libudev here is an example:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <libudev.h>
#include <iostream>
#include <fcntl.h>


int main(int argc, char *argv[])
{
    struct stat sb;

    // Get a file descriptor to the file.
    int fd = open(argv[1], O_RDWR);

    // Get stats for that file descriptor.
    if (fstat(fd, &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }

    // Create the udev context.
    struct udev *udev;
    udev = udev_new();

    // Create de udev_device from the dev_t obtained from stat.
    struct udev_device *dev;
    dev = udev_device_new_from_devnum(udev, 'b', sb.st_dev);

    // Finally obtain the node.
    const char* node  = udev_device_get_devnode(dev);

    udev_unref(udev);

    std::cout << "The file is in:    " << node << std::endl;

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM