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 ...
随机推荐
- java枚举使用详解(转)
在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的"数 ...
- uwsgi选择使用的python版本(转载)
大概如下 mkdir /data/uwsgi cd /data/uwsgi wget http://projects.unbit.it/downloads/uwsgi-2.0.11.tar.gz ta ...
- linux 文件权限 初级
sudo lsattr /etc/sudoers 查看属性 sudo vi index.html 以root权限编辑文件
- ASP.NET HighStock
参考博客HighCharts/Highstock使用小结,使用汉化及中文帮助文档 参考博客highcharts与highstock实例
- Java文件操作①——XML文件的读取
一.邂逅XML 文件种类是丰富多彩的,XML作为众多文件类型的一种,经常被用于数据存储和传输.所以XML在现今应用程序中是非常流行的.本文主要讲Java解析和生成XML.用于不同平台.不同设备间的数据 ...
- 做IT不能一辈子只靠技术生存
在中国你千万不要以为学习技术就可以换来稳定的生活和高的薪水待遇,你千万更不要认为哪些从事市场开发,跑腿的人,没有前途. 不知你是不是知道,咱们中国有相当大的一部分软件公司,他们的软件开发团队都小的可怜 ...
- ORA-16179: incremental changes to "log_archive_dest_1" not allowed with SPFILE
SQL> alter system set log_archive_dest_1='E:\arch ' scope=both; alter system set log_archive_dest ...
- java io读书笔记(7) Closing Output Streams
输出完毕后,需要close这个stream,从而使操作系统释放相关的资源.举例: public void close( ) throws IOException 并不是所有的stream都需要clos ...
- Swift游戏实战-跑酷熊猫(一) 简介 (含源代码)
优酷观看地址:http://v.youku.com/v_show/id_XNzM2Nzc2MTIw.html 通过这个小游戏,我们能够接触到物理系统(SKPhysicsBody,physicsWorl ...
- [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...