android4.2.2设置选项中的关于设备或者关于平板电脑的字段内容由来之/proc/version

本文解析了Android设备信息的来源,包括Linux内核信息和Android编译时生成的属性参数。详细介绍了如何通过特定文件获取这些信息,以及这些信息是如何被应用程序读取和展示的。

 

今天很好奇下面这张图片显示的字段内容从何而来,这些也常常作为Android手机或者平板中的设置项中”关于平板电脑“或者“关于设备”等信息相关。

 

调研学习确认后,初步定为到是通过如下文件来获取的。

1./proc/version/的内容如下

Linux version 3.3.0 (liuyongming@wits) (gcc version 4.6.3 20120201 (prerelease) (crosstool-NG linaro-1.13.1-2012.02-20120222 - Linaro GCC 2012.02) ) #13 SMP PREEMPT Thu Nov 7 20:35:22 CST 2013

这部分内容是自动通过编译器在编译的时候确定的,内核启动后会通过version_proc_show()等函数来创建好vesion并写入相关的内容

static int version_proc_show(struct seq_file *m, void *v)
{
	seq_printf(m, linux_proc_banner,
		utsname()->sysname,
		utsname()->release,
		utsname()->version);
	return 0;
}

核心的字段就是在linux_proc_banner这个宏变量中:

#include <generated/compile.h>
/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

const char linux_proc_banner[] =
	"%s version %s"
	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
	" (" LINUX_COMPILER ") %s\n";

很明显最终version的内容是通过上述的几个宏来整合确定 ,那么这些宏在哪里呢?

这些宏是在编译时,结合你的编译环境和编译器的版本最终自动确定的,确定的脚本由kernel目录/scripts/mkcompile.h来生成的,最终生成的文件保存在内核目录include/generated/compile.h中,而这个头文件也整合在编译时被加入到了Linux_banner[]所在的文件中。

 

2.上面是Linux内核专属的一些信息字段,作为android自己的东西,主要维护在内核的属性参数之中

/system/build.prop是由Android编译时由编译脚本build/core/Makefile和Shell脚本build/tools/buildinfo.sh来生成的,综合了整个编译配置环境下的平台相关变量,而这些变量往往在Android系统的关于设备信息中都能查看的到。

  3 ro.build.id=JDQ39
  4 ro.build.display.id=fiber_3g-eng 4.2.2 JDQ39 20140110 test-keys
  5 ro.build.version.incremental=20140110
  6 ro.build.version.sdk=17
  7 ro.build.version.codename=REL
  8 ro.build.version.release=4.2.2
  9 ro.build.date=2014年 01月 10日 星期五 16:03:07 CST
 10 ro.build.date.utc=1389340987
 11 ro.build.type=eng
 12 ro.build.user=root
 13 ro.build.host=linux
 14 ro.build.tags=test-keys
 15 ro.product.model=Softwinner
 16 ro.product.brand=Softwinner
 17 ro.product.name=fiber_3g
 18 ro.product.device=fiber-3g
 19 ro.product.board=exdroid
 20 ro.product.cpu.abi=armeabi-v7a
 21 ro.product.cpu.abi2=armeabi
 22 ro.product.manufacturer=unknown
 23 ro.product.locale.language=en
 24 ro.product.locale.region=US
 25 ro.wifi.channels=
 26 ro.board.platform=fiber
....

就这样,应用程序头通过读取这些文件的信息就可以把需要的字段display给大家查看,而开发者也可以修改这些字段,当然因为是编译时由脚本自动产生,所以也没必要修改太多。



 

这是题目要求:内容:编写一个内核模块,对PC本地收到的大小为n字节(icmp协议中的data部分大小)的ping包进行统计。 要求: 1.在netfilter的NF_INET_PRE_ROUTING监测点过滤报文 2.仅处理IPv4报文即可 3.n作为参数传入内核模块,范围为[100,1000] 4.可通过命令查看统计信息,包括报文数目、收到的时间、原IP地址等。 5.命令实现方式不限,如通过netlink实现,也可通过proc文件实现。 6.内核模块必须有module_init(),module_exit()两个函数 7.提供源码、设计文档。 这是代码:#include <linux/module.h> #include <linux/kernel.h> #include <linux/version.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/atomic.h> #define MOD_NAME "icmp_stat" #define PROC_FILE "icmp_stat" static int n = 100; // 默认统计100字节的包 module_param(n, int, 0644); MODULE_PARM_DESC(n, "ICMP data size to count (100-1000 bytes)"); static atomic_t packet_count = ATOMIC_INIT(0); // 原子计数器 // Netfilter钩子函数 static unsigned int icmp_stat_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *ip_header; struct icmphdr *icmp_header; unsigned int data_len; if (!skb) return NF_ACCEPT; // 获取IP头 ip_header = ip_hdr(skb); if (!ip_header || ip_header->protocol != IPPROTO_ICMP) return NF_ACCEPT; // 获取ICMP头(跳过IP头) icmp_header = (struct icmphdr *)(skb->data + (ip_header->ihl * 4)); if (!icmp_header || icmp_header->type != ICMP_ECHO) return NF_ACCEPT; // 计算数据部分长度 = 总长度 - IP头 - ICMP头 data_len = ntohs(ip_header->tot_len) - (ip_header->ihl * 4) - sizeof(struct icmphdr); // 检查是否符合指定大小 if (data_len == n) { atomic_inc(&packet_count); // 原子操作增加计数 } return NF_ACCEPT; } // Netfilter钩子配置 static struct nf_hook_ops nfho = { .hook = icmp_stat_hook, .hooknum = NF_INET_PRE_ROUTING, .pf = PF_INET, .priority = NF_IP_PRI_FIRST, }; // /proc文件处理函数 static int icmp_stat_proc_show(struct seq_file *m, void *v) { seq_printf(m, "ICMP packets with %d bytes data: %d\n", n, atomic_read(&packet_count)); return 0; } static int icmp_stat_proc_open(struct inode *inode, struct file *file) { return single_open(file, icmp_stat_proc_show, NULL); } static const struct file_operations proc_fops = { .owner = THIS_MODULE, .open = icmp_stat_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; // 模块初始化 static int __init icmp_stat_init(void) { // 验证参数范围 if (n < 100 || n > 1000) { printk(KERN_ERR "Invalid n value: %d. Must be 100-1000\n", n); return -EINVAL; } // 注册Netfilter钩子 int ret = nf_register_net_hook(&init_net, &nfho); if (ret) { printk(KERN_ERR "Failed to register netfilter hook\n"); return ret; } // 创建/proc文件 if (!proc_create(PROC_FILE, 0, NULL, &proc_fops)) { nf_unregister_net_hook(&init_net, &nfho); printk(KERN_ERR "Failed to create /proc/%s\n", PROC_FILE); return -ENOMEM; } printk(KERN_INFO "%s module loaded. Counting %d-byte ICMP packets\n", MOD_NAME, n); return 0; } // 模块退出 static void __exit icmp_stat_exit(void) { nf_unregister_net_hook(&init_net, &nfho); remove_proc_entry(PROC_FILE, NULL); printk(KERN_INFO "%s module unloaded\n", MOD_NAME); } module_init(icmp_stat_init); module_exit(icmp_stat_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("ICMP packet size statistics"); 帮我写软件设计书的如下部分:1. 前言 1 1.1. 项目简要说明 1 1.2. 任务概述 1 2. 需求分析 1 3. 原理概述 1 4. 系统构架描述 2 4.1. 概述 2 4.2. 模块结构 2 4.3. 核心代码 2 5. 实现效果 6
08-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值