方法
- 看看 /proc/version 文件,这将是内核版本的详细信息
- /usr/include/linux/version.h 文件将包含版本代码。解码版本然后你可以得到当前的内核版本。
/proc/version
-
/proc目录包含虚拟文件,其中包含有关系统内存、CPU内核、已安装文件系统等的信息,有关正在运行的内核的信息存储在/proc/version虚拟文件中。
-
使用cat或less来显示文件的内容:
$ cat /proc/version
Linux version 3.10.0-957.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Thu Nov 8 23:39:32 UTC 2018
/usr/include/linux/version.h
#define LINUX_VERSION_CODE 199168
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#define RHEL_MAJOR 7
#define RHEL_MINOR 6
#define RHEL_RELEASE_VERSION(a,b) (((a) << 8) + (b))
#define RHEL_RELEASE_CODE 1798
#define RHEL_RELEASE "957"
#define KERNEL_HEADERS_CHECKSUM "08e373f05de231b7b9b6ec5af5075ddc5410c0c4"
举个例子: 内核版本号为4.4.45,对应的LINUX_VERRSION_CODE 为263213,计算方法如下:
- 首先将4.4.45 转为16进制为 0x04.0x04.0x2D
- 然后宏 KERNEL_VERSION(0x04,0x04,0x2D)展开之后得到04042D 这个16进制的数字
- 最后将0x040423 转化为十进制就得到了十进制的263213 即为 LINUX_VERSION_CODE的值263213
可以利用下面的代码根据linux内核版本号的不同调用不同的API函数:
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
....//3.10.0 之前的API调用
#else
....//3.10.0 版本之后的API调用
#endif
举个例子:
#if defined(ACL_LINUX)
# include <linux/version.h>
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
# include <sys/eventfd.h>
# define HAS_EVENTFD
# else
# undef HAS_EVENTFD
# endif
#else
# undef HAS_EVENTFD
#endif
ACL_SOCKET fds[2];
#if defined(HAS_EVENTFD)
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
int flags = FD_CLOEXEC;
# else
int flags = 0;
# endif
fds[0] = eventfd(0, flags);
fds[1] = fds[0];
#else
if (acl_sane_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
acl_msg_error("%s(%d), %s: acl_duplex_pipe error %s",
__FILE__, __LINE__, __FUNCTION__, acl_last_serror());
return NULL;
}
#endif
关于:FD_CLOEXEC
- 一般来说,进程往往会调用fork函数来执行一个子进程,调用execve()执行其他程序,这时候可能就导致子进程存在一些无用的文件描述符
- 父进程在fork函数的时候,子进程会拷贝跟父进程一样的地址空间,包括寄存器,文件描述符,堆,栈等。在一开始,父进程与子进程的文件描述符执行的是系统文件表中同一项(包括文件状态,和文件偏移量)。
- 当我们用execve执行其他程序的时候,全新的程序会替换子进程中的地址空间,数据段、堆栈,此时保存与父进程文件描述符也就不存在了,也无法进行关闭,这时候就需要FD_CLOEXEC,表示子进程在执行exec的时候,该文件描述符就需要关闭
int fd=open("1",O_RDONLY);
//获取当前文件描述符的相关标志位
int flags=fcntl(fd,F_GETFD,NULL);
flags|=FD_CLOEXEC;
fcntl(fd,F_SETFD,flags);