fcntl函数参数F_GETPIPE_SZ、F_SETPIPE_SZ报错引出的关于linux-specific头文件的使用方法

直接来个例子说明:
----------------------------------- 
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
//#incude <fcntl.h>  //这里必须屏蔽掉
// Must use Linux specific fcntl header.
#include </usr/include/linux/fcntl.h>
/* add for compile warnning */
extern int fcntl(int fd, int cmd, ... /* arg */ );
extern int open( const char * pathname, int flags);
 
int pipe_resize(int fd, int pipe_resize) {
    if ( fd < 0 || pipe_resize > 1024*1024 || pipe_resize < 0 ){
        eloge(mTag, "param error!");
        return -1;
    }
    long pipe_size = (long)fcntl(fd, F_GETPIPE_SZ);
    
    if (pipe_size == -1) {
        perror("get pipe size failed.");
        return -1;
    }
    elogi(mTag, "default pipe size: %ld ", pipe_size);
    int ret = fcntl(fd, F_SETPIPE_SZ, pipe_resize);
    if (ret < 0) {
        perror("set pipe size failed.");
        return -1;
    }
    pipe_size = (long)fcntl(fd, F_GETPIPE_SZ);
    if (pipe_size == -1) {
        perror("get pipe size 2 failed.");
        return -1;
    }
    elogi(mTag, "new pipe size: %ld ", pipe_size);
    return 0;
}
-----------------------------------
对于代码里面
-----------------------------------
//#incude <fcntl.h>  //这里必须屏蔽掉
// Must use Linux specific fcntl header.
#include </usr/include/linux/fcntl.h>
/* add for compile warnning */
extern int fcntl(int fd, int cmd, ... /* arg */ );
extern int open( const char * pathname, int flags);
-----------------------------------
屏蔽掉//#incude <fcntl.h>,而使用#include </usr/include/linux/fcntl.h>和函数声明
原因见后文的linux-specific使用说明
 
可以不屏蔽//#incude <fcntl.h>,自己手动添加 F_SETPIPE_SZ和F_GETPIPE_SZ宏定义
=======
#define F_LINUX_SPECIFIC_BASE   1024
/*
* Set and get of pipe page size array
*/
#define F_SETPIPE_SZ    (F_LINUX_SPECIFIC_BASE + 7)
#define F_GETPIPE_SZ    (F_LINUX_SPECIFIC_BASE + 8)
=======
 
linux-specific使用说明:
从两个地方入手,首先得了解用户空间调用内核系统函数的过程
可以参考:
先了解 SYSCALL_DEFINEx 的使用方法
 
fcntl的例子网上的说明文章不多,以open为例
 
上面所有的参考都只为说明一点,用户空间的 fcntl函数的
最终实现在:
kernellinux-3.4.yfsfcntl.c
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
系统接口在:
kernellinux-3.4.yincludelinuxsyscalls.h
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
 
关于Linux系统调用(syscall)原理,不清楚的可以参考
 
对于系统函数的封装调用细节不管,但肯定是用户空间应用调用 ‘fcntl’,内核空间调用到 ‘sys_fcntl’
最终call到了kernellinux-3.4.yfsfcntl.c中SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)这个函数
而对于编译器默认路径,fcntl头文件路径是:
#include <fcntl.h> //即 /opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/usr/include/fcntl.h
这个头文件里面是没有F_GETPIPE_SZ、F_SETPIPE_SZ这些宏定义的
参考:https://linux.die.net/man/2/fcntl  它是linux独有的
所以需要用到另外一个路径的头文件/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/usr/include/linux/fcntl.h
用它就需要添加头文件包含
#include </usr/include/linux/fcntl.h> 
//实际上这里可以简写为 #include <linux/fcntl.h>,
//因为编译器默认路径已经包含到了/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/usr/include/
而此时打开这个fcntl.h你会发现里面并没有fcntl这个函数的声明,
但是编译器和连接器是可以从/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/usr/lib/libc.a或者libc.so中找到fcntl函数这个符号的
所以如果忽略警告的话,编译链接都没问题,只要参数不用错,也不会出问题。
但对于警告:
    error: implicit declaration of function ‘fcntl’ [-Werror=implicit-function-declaration]
    error: implicit declaration of function ‘open’ [-Werror=implicit-function-declaration]
不容忽视,详见下面链接的文章说明
 
所以我们需要再添加函数的声明
extern int fcntl(int fd, int cmd, ... /* arg */ );
extern int open( const char * pathname, int flags);
 
原文地址:https://www.cnblogs.com/cutelinux/p/7868332.html