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\n", 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\n", 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函数的
最终实现在:
kernel\linux-3.4.y\fs\fcntl.c
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
系统接口在:
kernel\linux-3.4.y\include\linux\syscalls.h
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
关于Linux系统调用(syscall)原理,不清楚的可以参考
对于系统函数的封装调用细节不管,但肯定是用户空间应用调用 ‘fcntl’,内核空间调用到 ‘sys_fcntl’
最终call到了kernel\linux-3.4.y\fs\fcntl.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);