Modultils工具源码分析之insmod篇 (5)

回到主战场INSMOD_MAIN

 

1610       /* And open it.  */

1611       if ((fp = gzf_open(filename, O_RDONLY)) == -1) {

1612              error("%s: %m", filename);

1613              return 1;

1614       }

1615       /* Try to prevent multiple simultaneous loads.  */

1616       if (dolock)

1617                          flock(fp, LOCK_EX);

 

gzf_open首先按压缩方式打开文件,然后在尝试非压缩方式。如果要求加锁,那就满足要求。

 

1618       if (!get_kernel_info(K_SYMBOLS))

1619              goto out;

 

函数get_kernel_info./modutils-2.4.0/util/modstat.c中。

Insmod——get_kernel_info函数

409  int get_kernel_info(int type)

410  {

411         k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);

412

413  #ifdef COMPAT_2_0

414         if (!k_new_syscalls)

415                return old_get_kernel_info(type);

416  #endif /* COMPAT_2_0 */

417

418         return new_get_kernel_info(type);

419  }

 

411行的作用是测试内核的版本,sys_query_module这个系统调用是在v2.1.x以后才加入的,如果版本比这个早,就会返回-NOSYSnew_get_kernel_info是这个函数的核心,它也在这个文件里。

Insmod——new_get_kernel_info函数

84    static int new_get_kernel_info(int type)

85    {

86           struct module_stat *modules;

87           struct module_stat *m;

88           struct module_symbol *syms;

89           struct module_symbol *s;

90           size_t ret;

91           size_t bufsize;

92           size_t nmod;

93           size_t nsyms;

94           size_t i;

95           size_t j;

96           char *module_names;

97           char *mn;

98

99           drop();

100

101         /*

102         * Collect the loaded modules

103         */

104         module_names = xmalloc(bufsize = 256);

105         while (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {

106                if (errno != ENOSPC) {

107                       error("QM_MODULES: %m/n");

108                       return 0;

109                }

110                module_names = xrealloc(module_names, bufsize = ret);

111         }

112         module_name_list = module_names;

113         l_module_name_list = bufsize;

114         n_module_stat = nmod = ret;

115         module_stat = modules = xmalloc(nmod * sizeof(struct module_stat));

116         memset(modules, 0, nmod * sizeof(struct module_stat));

117

118         /* Collect the info from the modules */

119         for (i = 0, mn = module_names, m = modules;

120              i < nmod;

121              ++i, ++m, mn += strlen(mn) + 1) {

122                struct module_info info;

123

124                m->name = mn;

125                if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {

126                       if (errno == ENOENT) {

127                       /* The module was removed out from underneath us. */

128                              m->flags = NEW_MOD_DELETED;

129                              continue;

130                       }

131                       /* else oops */

132                       error("module %s: QM_INFO: %m", mn);

133                       return 0;

134                }

135

136                m->addr = info.addr;

137

138                if (type & K_INFO) {

139                       m->size = info.size;

140                       m->flags = info.flags;

141                       m->usecount = info.usecount;

142                       m->modstruct = info.addr;

143                }

144

145                if (type & K_REFS) {

146                       int mm;

147                       char *mrefs;

148                       char *mr;

149

150                       mrefs = xmalloc(bufsize = 64);

151                       while (query_module(mn, QM_REFS, mrefs, bufsize, &ret)) {

152                              if (errno != ENOSPC) {

153                                     error("QM_REFS: %m");

154                                     return 1;

155                              }

156                              mrefs = xrealloc(mrefs, bufsize = ret);

157                       }

158                       for (j = 0, mr = mrefs;

159                            j < ret;

160                            ++j, mr += strlen(mr) + 1) {

161                              for (mm = 0; mm < i; ++mm) {

162                                     if (strcmp(mr, module_stat[mm].name) == 0) {

163                                            m->nrefs += 1;

164                                            m->refs=xrealloc(m->refs, m->nrefs * sizeof(struct module_stat **));

165                                            m->refs[m->nrefs - 1] = module_stat + mm;

166                                            break;

167                                     }

168                              }

169                       }

170                       free(mrefs);

171                }

172

173                if (type & K_SYMBOLS) { /* Want info about symbols */

174                       syms = xmalloc(bufsize = 1024);

175                       while (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {

176                              if (errno == ENOSPC) {

177                                     syms = xrealloc(syms, bufsize = ret);

178                                     continue;

179                              }

180                              if (errno == ENOENT) {

181                              /*

182                              * The module was removed out

183                              * from underneath us.

184                              */

185                                     m->flags = NEW_MOD_DELETED;

186                                     free(syms);

187                                     goto next;

188                              } else {

189                                     error("module %s: QM_SYMBOLS: %m", mn);

190                                     return 0;

191                              }

192                       }

193                       nsyms = ret;

194

195                       m->nsyms = nsyms;

196                       m->syms = syms;

197

198                       /* Convert string offsets to string pointers */

199                       for (j = 0, s = syms; j < nsyms; ++j, ++s)

200                              s->name += (unsigned long) syms;

201                }

202                next:

203         }

204

205         if (type & K_SYMBOLS) { /* Want info about symbols */

206                /* Collect the kernel's symbols.  */

207                syms = xmalloc(bufsize = 16 * 1024);

208                while (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {

209                       if (errno != ENOSPC) {

210                              error("kernel: QM_SYMBOLS: %m");

211                              return 0;

212                       }

213                       syms = xrealloc(syms, bufsize = ret);

214                }

215                nksyms = nsyms = ret;

216                ksyms = syms;

217

218                /* Convert string offsets to string pointers */

219                for (j = 0, s = syms; j < nsyms; ++j, ++s)

220                       s->name += (unsigned long) syms;

221         }

222

223         return 1;

224          }

 

99行的drop,首先清除module_stat的内容。module_stat是个全局变量,用于保存模块信息。105行获取所有内核模块的名字。然后在119行,获取所有模块的信息,这些信息以module_info结构保存。这个结构在linux/include/linux/module.h中定义。

 

95    struct module_info

96    {

97           unsigned long addr;

98           unsigned long size;

99           unsigned long flags;

100         long usecount;

101  };

 

接下来,由于typeK_SYMBOLS,所以执行173行的if块,获取各个模块的符号信息。在205行还要查询一次模块符号信息,不过这次模块名没有指定,查的是内核模块的符号(查询模块信息时,内核模块是不被查阅的)。

INSMOD_MAIN中接下来设置当待加载模块与内核版本不符时,要使用的前后缀。

Insmod——set_ncv_prefix函数

136  /* Only set prefix once. If set by the user, use it.  If not set by the

137  * user, look for a well known kernel symbol and derive the prefix from

138  * there.  Otherwise set the prefix depending on whether uts_info

139  * includes SMP or not for backwards compatibility.

140  */

141  static void set_ncv_prefix(char *prefix)

142  {

143         static char derived_prefix[256];

144         static const char *well_known_symbol[] = { "get_module_symbol_R",

145                                               "inter_module_get_R",

146                                            };

147         struct module_symbol *s;

148         int i, j, l, m, pl;

149         const char *name;

150         char *p;

151 

152         if (ncv_prefix)

153                return;

154 

155         if (prefix)

156                ncv_prefix = prefix;

157         else {

158                /* Extract the prefix (if any) from well known symbols */

159                for (i = 0, s = ksyms; i < nksyms; ++i, ++s) {

160                       name = (char *) s->name;

161                       l = strlen(name);

162                       for (j = 0; j < sizeof(well_known_symbol)/sizeof(well_known_symbol[0]); ++j) {

163                              m = strlen(well_known_symbol[j]);

164                              if (m + 8 > l ||

165                                  strncmp(name, well_known_symbol[j], m))

166                                     continue;

167                              pl = l - m - 8;

168                              if (pl > sizeof(derived_prefix)-1)

169                                     continue; /* Prefix is wrong length */

170                              /* Must end with 8 hex digits */

171                              (void) strtoul(name+l-8, &p, 16);

172                              if (*p == 0) {

173                                     strncpy(derived_prefix, name+m, pl);

174                                     *(derived_prefix+pl) = '/0';

175                                     ncv_prefix = derived_prefix;

176                                     break;

177                              }

178                       }

179                }

180         }

181         if (!ncv_prefix) {

182                p = strchr(uts_info.version, ' ');

183                if (p && *(++p) && !strncmp(p, "SMP ", 4))

184                       ncv_prefix = "smp_";

185                else

186                       ncv_prefix = "";

187         }

188         ncv_plen = strlen(ncv_prefix);

189         if (flag_verbose)

190                lprintf("Symbol version prefix '%s'", ncv_prefix);

191  }

 

ncv_prefix可由用户指定,只能设置一次。如果用户没有设定,则系统通过157~180行进行设置。规则很简单,在内核模块符号里查找以“get_module_symbol_R”和“inter_module_get_R”开头的符号(我猜‘R’应该是release的意思,所以后面跟的一定是版本信息),如果存在这样的符号而且符号的最后八个子符是16进制数字,就取这八个数字作为ncv_prefix的内容。如果找不到这样的符号(不大可能),那就看通过sys_newuname获取的版本信息,如果是SMP体系(对称多CPU),将ncv_prefix设为“smp_”,否则就认为无关紧要。

接下来INSMOD_MAIN检查待安装的模块是否已经加载。如果已经加载了,当然就不能往下走了。

 

1627       for (i = 0; i < n_module_stat; ++i) {

1628              if (strcmp(module_stat[i].name, m_name) == 0) {

1629                     error("a module named %s already exists", m_name);

1630                     goto out;

1631              }

1632       }

1633

1634       error_file = filename;

1635       if ((f = obj_load(fp, ET_REL, filename)) == NULL)

1636                          goto out;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值