Reputation: 1313
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.
Upvotes: 1
Views: 3958
Reputation: 14360
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;
}
Upvotes: 1
Reputation: 86323
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.
Upvotes: 1
Reputation: 1
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).
Upvotes: 0