ioctl函数操作----FIOSETOWN和FIOGETOWN

  FIOSETOWN和FIOGETOWN用来设置文件描述符的进程ID或进程组ID,在《Unix网络编程》卷一中有下面的图

这个图是在第二版的16.3节,图中FIOSETOWN和FIOGETOWN操作时第三个参数所需要的类型均int类型,我感觉这个地方不太准确(个人理解,或者跟作者的想法不同,或者作者这个地方出现了遗漏)。因为FIOSETOWN和FIOGETOWN操作时,第三个参数的类型应该分别为const int * 和int *。这个地方还有一个地方,个人感觉不妥,FIOGETOWN和FIOSETOWN这两个归于“文件”操作之列,但是在调用ioctl并且指定FIOGETOWN或FIOSETOWN时,如果第一个参数是普通文件的描述符,接口会报ENOTTY错误。所以根据测试的结果FIOGETOWN、FIOSETOWN应该只能作用于套接字。另外一个依据是在FIOGETOWN、FIOSETOWN定义的头文件中的注释,其完整的头文件如下所示:

#ifndef __ASM_GENERIC_SOCKIOS_H
#define __ASM_GENERIC_SOCKIOS_H

/* Socket-level I/O control calls. */
#define FIOSETOWN   0x8901
#define SIOCSPGRP   0x8902
#define FIOGETOWN   0x8903
#define SIOCGPGRP   0x8904
#define SIOCATMARK  0x8905
#define SIOCGSTAMP  0x8906      /* Get stamp (timeval) */
#define SIOCGSTAMPNS    0x8907      /* Get stamp (timespec) */

#endif /* __ASM_GENERIC_SOCKIOS_H */

注释“/* Socket-level I/O control calls. */”的意思就是说这些操作是在套接字级别(直译,英文太烂),所以大胆认为书本中这个地方处理的不是很恰当。当然stevens大师的作品的经典毋庸置疑,我也是看他的书本入门的,这里只是把一些疑问和自己的想法跟大家分享一下,希望相互学习,共同进步。下面给出我的测试程序和输出结果。

一、 使用普通文件描述符

  测试程序如下:

#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>


int main(void)
{
    int     own = -1;
    int     fd = -1;
    pid_t   pid;

    pid = getpid();
    if ((fd = open("test_file", O_RDWR)) < 0) {
        fprintf(stderr, "open: %s, errno = %d\n", 
                strerror(errno), errno);
        return -1;
    }
    if (ioctl(fd, FIOGETOWN, &own) < 0) {
        fprintf(stderr, "ioctl get: %s, errno = %d\n", 
                strerror(errno), errno);
        return -1;
    }
    printf("pid = %d, own = %d\n", pid, own);
    if (ioctl(fd, FIOSETOWN, &pid) < 0) {
        fprintf(stderr, "ioctl set: %s, errno = %d\n", 
                strerror(errno), errno);
        return -1;
    }
    return 0;
}

其中test_file是我建立的一个普通文件,从代码中可以看出这个fd是通过打开一个文件获取的,然后直接执行ioctl操作,其结果如下所示:

ioctl get: Inappropriate ioctl for device, errno = 25

错误码25就是错误ENOTTY,出现这个错误的原因是“The  specified  request  does  not apply to the kind of object that the descriptor d references”或者“d is not associated with a character special device”(d是第一个参数)。所以从这里可以看出,FIOSETOWN和FIOGETOWN不能作用于普通文件描述符,其余其他的文件类型管道、符号链接等读者可以自行测试,我也不知道可不可以。

二、使用套接字

测试程序如下:

#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>


int main(void)
{
    int     own = -1;
    int     fd = -1;
    pid_t   pid;

    pid = getpid();
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (ioctl(fd, FIOGETOWN, &own) < 0) {
        fprintf(stderr, "ioctl get: %s, errno = %d\n", 
                strerror(errno), errno);
        fprintf(stderr, "ioctl get: %s\n", strerror(ENOTTY));
        return -1;
    }
    printf("pid = %d, own = %d\n", pid, own);
    if (ioctl(fd, FIOSETOWN, &pid) < 0) {
        fprintf(stderr, "ioctl set: %s, errno = %d\n", 
                strerror(errno), errno);
        return -1;
    }
    return 0;
}


这个程序和上面唯一的不同就是文件描述符的获取,这个的文件描述符是套接字,其输出结构如下所示:

pid = 2194, own = 0


没有任何错误输出。这里还有一个细节需要注意,新创建的套接字其所有者是进程0,这个不知道是因为初始化的问题还是因为这个套接字是进程0创建的。这个问题,只有看内核源码才能解答了。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值