C/C++编程:如何识别Linux内核版本

1059 篇文章 280 订阅

方法

  • 看看 /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);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值