如何打开指定范围的文件描述符

linux系统中在打开描述符时,默认打开的都是最小的空闲描述符。第一个被打开的文件描述符一般是3,默认0/1/2 为输入输出和标准错误描述符。

那么如果我们想打开某一个特定的描述符时要如何操作呢?。

更进一步说我们需要打开一个指定范围的描述符,用于给不同的模块保留不同范围的描述符,以免不同的模块之间描述符相互交织。那么如何操作呢?。

这里主要需要解决的是两个问题,一个是如何打开特定的文件描述符,另一个是如何保证这个特定的描述符是可以使用的。前者使用dup2将文件描述符进行复制。后者则使用fcntl对文件描述符的状态进行判断。

dup2 实现打开特定的文件描述符

man dup可以查看到dup2的定义如下

       int dup2(int oldfd, int newfd);

   dup2()
       The dup2() system call performs the same task as dup(), but instead of using the lowest-numbered unused file descriptor, it uses the descriptor number specified in newfd.  If
       the descriptor newfd was previously open, it is silently closed before being reused.

执行类似dup的操作,dup函数创建当前fd的拷贝,使用最小的未使用的文件描述符返回作为新描述符。dup2使用指定的描述符newfd作为拷贝的目标。如果newfd之前是打开的,就会直接关闭掉然后重用。

使用dup2 以指定的描述符打开文件的形式如下,这样path就是以target_fd来打开了。

int open_target_fd(char * path,int target_fd){
        int fd = 0;
        fd = open(path,O_RDWR|O_CREAT,0777);
        if (fd < 0 ){
                perror("open");
                return -1;
        }else{
                dup2(fd,target_fd);
                close(fd);
                return target_fd;
        }
}

fcntl判断文件描述符是否在被使用

fcntl主要是通过各种命令来对fd的状态进行查询和修改。

       int fcntl(int fd, int cmd, ... /* arg */ );
       
              fcntl() performs one of the operations described below on the open file descriptor fd.  The operation is determined by cmd.

       F_GETFL (void)
              Get the file access mode and the file status flags; arg is ignored.
              
RETURN VALUE

       F_GETFL  Value of file status flags.

通过如下的check_fd_inuse函数可以判断fd是否在被使用,如果返回1就是正在被使用,如果返回0就是没有被使用。

int check_fd_inuse(int fd){
        struct stat _stat;
        int ret = -1;
        if(0 <= fcntl(fd, F_GETFL,0)) {
                if(0 == fstat(fd, &_stat)) {
                        if(_stat.st_nlink >= 1){
                                ret = 0;
                                return 1 ;
                        }
                        else{
                                printf("File was deleted!\n");
                                return 0 ;
                        }
                }else{
                        perror("fstat error\n");
                        return 0;
                }
        }else{
                printf("fcntl error %d errono{%d}\n",fd,errno);
                return 0;
        }
}

实现打开指定范围的描述符

将上述两个主要环节进行组合就可以实现打开指定范围的描述的功能。

int open_specified_fd(int value){

        int fd = 0;
        fd = open("/dev/null",O_RDONLY);

        dup2(fd,value);
        close(fd);
}

int check_fd_inuse(int fd){
        struct stat _stat;
        int ret = -1;
        if(0 <= fcntl(fd, F_GETFL,0)) {
                if(0 == fstat(fd, &_stat)) {
                        if(_stat.st_nlink >= 1){
                                ret = 0;
                                return 1 ;
                        }
                        else{
                                printf("File was deleted!\n");
                                return 0 ;
                        }
                }else{
                        perror("fstat error\n");
                        return 0;
                }
        }else{
                printf("fcntl error %d errono{%d}\n",fd,errno);
                return 0;
        }
}

/*start from 500 end to 600*/
int open_fd_in_range(char * path){

        int start = 500;
        int fd = 0;
        while(1){
                if (check_fd_inuse(start) == 0){
                        break;
                }else{
                        start++;
                        if (start > 600){
                                return -1;
                        }
                }
        }
        fd = open(path,O_RDWR|O_CREAT,0777);
        if (fd < 0 ){
                perror("open");
                return -1;
        }else{
                dup2(fd,start);
                close(fd);
                return fd;
        }
}

int main(){
        open_specified_fd(500);
        open_specified_fd(501);
        open_fd_in_range("./123");
        open_fd_in_range("./456");
        while(1){
                sleep(1000);
        }
}

查看对应进程的proc的结果如下,可以看到打开了指定范围的描述符且:

lrwx------ 1 pi pi 64 Feb 26 18:14 0 -> /dev/pts/0
lrwx------ 1 pi pi 64 Feb 26 18:14 1 -> /dev/pts/0
lrwx------ 1 pi pi 64 Feb 26 18:14 2 -> /dev/pts/0
lr-x------ 1 pi pi 64 Feb 26 18:14 500 -> /dev/null
lr-x------ 1 pi pi 64 Feb 26 18:14 501 -> /dev/null
lrwx------ 1 pi pi 64 Feb 26 18:14 502 -> /path/to/test/123
lrwx------ 1 pi pi 64 Feb 26 18:14 503 -> /path/to/test/456

参考:
https://www.man7.org/linux/man-pages/man2/fcntl.2.html]

https://blog.csdn.net/kangear/article/details/42805393 (该博客中描述的判断文件描述符有效的办法,个人认为存在少许的问题)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值