mount源码分析 【转】
转自:http://blog.chinaunix.net/uid-10769062-id-3230811.html
Busybox-1.9.
在util-linux/mount.c的line:1609行首先映入眼帘的是:
int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
由于busybox是一个box,里面包含很多的可执行程序,如果cp,mount,umount等我们常用的一些命令,所以每个命令单独写入一个文件,而每个文件中也用类似mount_main()这样的命名方法作为局部的main函数。
MAIN_EXTERNALLY_VISIBLE的定义在 busybox-1.9./include/libbb.h中
如下:
/* We need to export XXX_main from libbusybox
* only if we build "individual" binaries
*/
#if ENABLE_FEATURE_INDIVIDUAL
#define MAIN_EXTERNALLY_VISIBLE EXTERNALLY_VISIBLE
#else
#define MAIN_EXTERNALLY_VISIBLE
#endif
而 EXTERNALLY_VISIBLE的定义在 busybox-1.9./include/platform.h中,line:73如下 /* -fwhole-program makes all symbols local. The attribute externally_visible
forces a symbol global. */
# if __GNUC_PREREQ (,)
# define EXTERNALLY_VISIBLE __attribute__(( visibility("default") ));
//__attribute__ ((__externally_visible__))
# else
# define EXTERNALLY_VISIBLE
# endif /* GNUC >= 4.1 */ 其中,__GNUC_PREREQ() 是什么意思呢? 在 busybox-1.9./include/platform.h,line:
/* Convenience macros to test the version of gcc. */
#undef __GNUC_PREREQ
#if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << ) __GNUC_MINOR__ >= ((maj) << ) (min))
#else
# define __GNUC_PREREQ(maj, min)
#endif 首先取消 __GNUC_PREREQ原来的宏定义,然后再根据__GNUC__ 和__GNUC_MINOR__的情况重新定义 __GNUC_PREREQ。
#undef 是在后面取消以前定义的宏定义§
其中, __GNUC__ 是gcc编译器编译代码时预定义的一个宏,他的值表示当前GCC的版本号,可以通过查看gcc版确定一下。
然后 __GNUC_MINOR__的含义也就可以推出了。 The macro contains the minor version number of the compiler. This can be used to work around differences between different releases of the compiler. It must always be used together with __GNUC__§. 返回去看
# if __GNUC_PREREQ (,)
其实就是看当前的GCC版本是否>=.1然后再做下一步判断。
接下来的:
#define EXTERNALLY_VISIBLE __attribute__(( visibility("default") ));
重点在于:
__attribute__(( visibility("default") ));
通过这个链接:http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html可知__attribute__ 的强大,可对变量,函数等symbols 对外的可见属性进行修改:
visibility ("visibility_type")
The visibility attribute on ELF targets causes the declaration to be emitted with default, hidden, protected or internal visibility.
void __attribute__ ((visibility ("protected")))
f () { /* Do something. */; }
int i __attribute__ ((visibility ("hidden"))); See the ELF gABI for complete details, but the short story is:
default
Default visibility is the normal case for ELF. This value is available for the visibility attribute to override other options that may change the assumed visibility of symbols. hidden
Hidden visibility indicates that the symbol will not be placed into the dynamic symbol table, so no other module (executable or shared library) can reference it directly. internal
Internal visibility is like hidden visibility, but with additional processor specific semantics. Unless otherwise specified by the psABI, GCC defines internal visibility to mean that the function is never called from another module. Note that hidden symbols, while they cannot be referenced directly by other modules, can be referenced indirectly via function pointers. By indicating that a symbol cannot be called from outside the module, GCC may for instance omit the load of a PIC register since it is known that the calling function loaded the correct value. protected
Protected visibility indicates that the symbol will be placed in the dynamic symbol table, but that references within the defining module will bind to the local symbol. That is, the symbol cannot be overridden by another module.
Not all ELF targets support this attribute. 接下来
/* parse long options, like --bind and --move. Note that -o option
* and --option are synonymous. Yes, this means --remount,rw works. */ for (i = j = ; i < argc; i )
{
if (argv[i][] == '-' && argv[i][] == '-')
{
append_mount_options(&cmdopts, argv[i] );
}
else
{
argv[j ] = argv[i];
}
}
argv[j] = ;
argc = j;
主要目的是解析命令行中的参数和选项,针对的是带有 "- -" 类型的长选项,实际上,- - 和 - 是一样的。主要是通过 append_mount_options()这个函数完成,进入 append_mount_options()。
其中,cmdopts是一个指针,它通过
char *cmdopts = xstrdup(""), busybox-1.9./util-linux/mount.c line: /* Append mount options to string */
static void append_mount_options(char **oldopts, const char *newopts)
{
if (*oldopts && **oldopts) {
/* do not insert options which are already there */
while (newopts[]) {
char *p;
int len = strlen(newopts);
p = strchr(newopts, ',');
if (p) len = p - newopts;
p = *oldopts;
while () {
if (!strncmp(p, newopts, len)
&& (p[len] == ',' || p[len] == '\0'))
goto skip;
p = strchr(p,',');
if (!p) break;
p ;
}
p = xasprintf("%s,%.*s", *oldopts, len, newopts);
free(*oldopts);
*oldopts = p;
skip:
newopts = len;
while (newopts[] == ',') newopts ;
}
} else {
if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts);
*oldopts = xstrdup(newopts);
}
} -- : if (!argc)
{
if (!(opt & OPT_ALL)) {
FILE *mountTable = setmntent(bb_path_mtab_file, "r");
printf("[%s:%d]bb_path_mtab_file=%s\n",__FILE__,__LINE__,bb_path_mtab_file); if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file); while (getmntent_r(mountTable, &mtpair[], getmntent_buf,sizeof(getmntent_buf)))
{
// Don't show rootfs. FIXME: why??
// util-linux 2.12a happily shows rootfs...
//if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue; if (!fstype || !strcmp(mtpair->mnt_type, fstype))
{
printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,mtpair->mnt_dir, mtpair->mnt_type,mtpair->mnt_opts);
}
}
if (ENABLE_FEATURE_CLEAN_UP)
{
endmntent(mountTable);
}
return EXIT_SUCCESS;
}
}
else
{
storage_path = bb_simplify_path(argv[]);
} line: 到line1765是依次从bb_path_mtab指向的文件中读取一行一行的数据,这些数据是 struct mntent格式的。Line1761 到line1763是打印出来的信息,如在命令行下直接输入:mount则显示: [zl@zhanglei ~]$ mount
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
devtmpfs on /dev type devtmpfs (rw,nosuid,relatime,seclabel,size=956748k,nr_inodes=,mode=)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,seclabel,gid=,mode=,ptmxmode=)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,relatime,seclabel)
/dev/sda3 on / type ext4 (rw,relatime,seclabel,user_xattr,acl,barrier=,data=ordered)
tmpfs on /run type tmpfs (rw,nosuid,nodev,relatime,seclabel,mode=)
selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (rw,nosuid,nodev,noexec,relatime,seclabel,mode=)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
systemd- on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=,pgrp=,timeout=,minproto=,maxproto=,direct)
mqueue on /dev/mqueue type mqueue (rw,relatime,seclabel)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel)
securityfs on /sys/kernel/security type securityfs (rw,relatime)
tmpfs on /media type tmpfs (rw,nosuid,nodev,noexec,relatime,rootcontext=system_u:object_r:mnt_t:s0,seclabel,mode=)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
/dev/sda5 on /mnt/sda5 type ext2 (rw,relatime,seclabel,user_xattr,acl,barrier=)
/dev/sda6 on /mnt/sda6 type ext2 (rw,relatime,seclabel,user_xattr,acl,barrier=)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
gvfs-fuse-daemon on /home/zl/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,relatime,user_id=,group_id=)
[zl@zhanglei ~]$ 同时查看/etc/fstab的内容为: [zl@zhanglei ~]$ cat /etc/fstab #
# /etc/fstab
# Created by anaconda on Thu Dec ::
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(), findfs(), mount() and/or blkid() for more info
#
UUID=a95fe862-ce64-485c-8bc6-10c3047b2fdb / ext4 defaults
UUID=869aca65-bf53-48e1-ab81-e6d2296cb818 swap swap
mount源码分析 【转】的更多相关文章
- Spring源码分析——资源访问利器Resource之实现类分析
今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...
- Solr初始化源码分析-Solr初始化与启动
用solr做项目已经有一年有余,但都是使用层面,只是利用solr现有机制,修改参数,然后监控调优,从没有对solr进行源码级别的研究.但是,最近手头的一个项目,让我感觉必须把solrn内部原理和扩展机 ...
- Docker源码分析(九):Docker镜像
1.前言 回首过去的2014年,大家可以看到Docker在全球刮起了一阵又一阵的“容器风”,工业界对Docker的探索与实践更是一波高过一波.在如今的2015年以及未来,Docker似乎并不会像其他昙 ...
- Vue.js 源码分析(三十一) 高级应用 keep-alive 组件 详解
当使用is特性切换不同的组件时,每次都会重新生成组件Vue实例并生成对应的VNode进行渲染,这样是比较花费性能的,而且切换重新显示时数据又会初始化,例如: <!DOCTYPE html> ...
- Vue.js 源码分析(二十七) 高级应用 异步组件 详解
当我们的项目足够大,使用的组件就会很多,此时如果一次性加载所有的组件是比较花费时间的.一开始就把所有的组件都加载是没必要的一笔开销,此时可以用异步组件来优化一下. 异步组件简单的说就是只有等到在页面里 ...
- Vue.js 源码分析(三) 基础篇 模板渲染 el、emplate、render属性详解
Vue有三个属性和模板有关,官网上是这样解释的: el ;提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 template ;一个字符串模板作为 Vue 实例的标识使用.模板将会 ...
- Vue.js 源码分析(九) 基础篇 生命周期详解
先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate.created.beforeMount.mounted.beforeupdate.updated .beforeDes ...
- Vue.js 源码分析(十二) 基础篇 组件详解
组件是可复用的Vue实例,一个组件本质上是一个拥有预定义选项的一个Vue实例,组件和组件之间通过一些属性进行联系. 组件有两种注册方式,分别是全局注册和局部注册,前者通过Vue.component() ...
- Vue源码分析(二) : Vue实例挂载
Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...
随机推荐
- bind和unbind事件的应用
1.bind 先从一动画的示例看起,如图: 而图中表示的mouseout(移出).mouseover(移入)事件的操作,比较简单,具体代码如下: 从中我可以得出bind()的语法: $().bind( ...
- 使用Docker搭建consul集群+registrator实现服务自动注册。
准备工作:10.173.16.83 master10.172.178.76 node110.171.19.139 node210.162.204.252 node3 一.安装consul-cluste ...
- CentOS6.5Minimal安装Gitlab7.5
文章出处:http://www.restran.net/2015/04/09/gilab-centos-installation-note/ 在 CentOS 6.5 Minimal 系统环境下,用源 ...
- js工具类大全
/********** 日期处理函数 *********/<script type="text/javascript" src="${springMacroRequ ...
- Fluentd安装——通过rpm方式
0. td-agent是何物 为了灵活性,fluentd用Ruby写的,其中一些性能敏感的部件使用c写的.普通的用户直接安装和使用Ruby进程可能有困难,这样就把它封装成Fluentd的稳定版本——t ...
- 分享书籍[writing idiomatic python ebook]
你是不是总是觉得学了python好久,蓦然回首,总是感觉写的代码不是那么有pythonic的味道.看看别人的代码(django,webpy),再看看自己的代码,觉得就是一java-python的混合体 ...
- wpf 面试题目
初级工程师 解释什么是依赖属性,它和以前的属性有什么不同?为什么在WPF会使用它?什么是样式什么是模板绑定(Binding )的基础用法解释这几个类的作用及关系: Visual, UIElement, ...
- git提交
1.git pull 本地已经commit 2.git checkout master 3.git pull 4.git checkout - 5.git merge master 6.git pus ...
- AJAX简单的数据增删改与分页应用
运行截图: PageBar.js: /* * 说明: * 整体思想,1.第一页时不显示:首页,上一页, * 2.最后一页时不显示:下一页,尾页 * 3.中间有 5 页导航, * 若:3.1.(总页数& ...
- 20145207 《Java程序设计》第8周学习总结
前言: 这两天电路焊小车,有意思归有意思,确实挺忙的.博客到现在才写.执勤看的东西忘得好快呀,莫名的记不住.不说废话了,开始. 教材学习内容总结: 一.NIO和NIO2 1.NIO的定义 InputS ...