成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux的ldconfig命令的代碼原理:ldconfig如何從指定目錄中查找動(dòng)態(tài)庫(kù)文件信息?

系統(tǒng) Linux
通過(guò)本系列文章對(duì)Linux 的ldconfig命令的源碼,從讀動(dòng)態(tài)緩存文件、打印庫(kù)緩存信息、查找/etc/ld.so.conf 指定的目錄的動(dòng)態(tài)庫(kù)信息等功能做了原理分析。

ldconfig的代碼中,search_dir()函數(shù)的關(guān)鍵內(nèi)容[1]

這部分關(guān)鍵代碼,負(fù)責(zé)查找指定目錄的動(dòng)態(tài)庫(kù)文件,與系統(tǒng)已有的ld.so.cache的記錄對(duì)比,如果有變化或系統(tǒng)緩存記錄中不存在,則將當(dāng)前動(dòng)態(tài)庫(kù)的信息加入到緩存信息鏈表。

/* Add library to list.  將動(dòng)態(tài)庫(kù)信息添加到鏈表*/
      struct dlib_entry *dlib_ptr;
      for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
 {
   /* Is soname already in list?  檢查SONAME記錄在鏈表中是否已存在,避免同一個(gè)庫(kù)重復(fù)添加多次*/
   if (strcmp (dlib_ptr->soname, soname) == 0)
     {
       /* Prefer a file to a link, otherwise check which one
   is newer.  
         SONAME的判定,以常規(guī)文件為優(yōu)先來(lái)源,而不優(yōu)先以鏈接文件作為SONAME的來(lái)源。
         */
       if ((!is_link && dlib_ptr->is_link)
    || (is_link == dlib_ptr->is_link
        && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
  {
    /* It s newer - add it.  */
    /* Flag should be the same - sanity check.  */
    if (dlib_ptr->flag != flag)
      {
        if (dlib_ptr->flag == FLAG_ELF
     && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
   dlib_ptr->flag = flag;
        else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
    || dlib_ptr->flag == FLAG_ELF_LIBC6)
          && flag == FLAG_ELF)
   dlib_ptr->flag = flag;
        else
   error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
          dlib_ptr->name, direntry->d_name,
          entry->path);
      }
    free (dlib_ptr->name);
    dlib_ptr->name = xstrdup (direntry->d_name);
    dlib_ptr->is_link = is_link;
    dlib_ptr->osversion = osversion;
    dlib_ptr->isa_level = isa_level;
  }
       /* Don t add this library, abort loop.  */
       /* Also free soname, since it s dynamically allocated.  */
       free (soname);
       break;
     }
 }
      /* Add the library if it s not already in.  
        如果該動(dòng)態(tài)庫(kù)沒(méi)在緩存列表中,則添加到鏈表記錄中。
        這里看到,動(dòng)態(tài)庫(kù)的信息分為name、SONAME、flag、是否為鏈接、os版本、isa_level這幾個(gè)方面
      */
      if (dlib_ptr == NULL)
 {
   dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
   dlib_ptr->name = xstrdup (direntry->d_name);
   dlib_ptr->soname = soname;
   dlib_ptr->flag = flag;
   dlib_ptr->is_link = is_link;
   dlib_ptr->osversion = osversion;
   dlib_ptr->isa_level = isa_level;
   /* Add at head of list.  */
   dlib_ptr->next = dlibs;
   dlibs = dlib_ptr;
 }
    }

繼續(xù)處理,下面代碼仍然是 search_dir()函數(shù)的代碼,用于核對(duì)得到的緩存信息列表的文件,把那些指向軟鏈接的軟鏈接文件,判斷為多余的記錄(節(jié)點(diǎn)),給予剔除。

ldconfig的幫助文檔[2]說(shuō),/etc/ld.so.cache 文件的內(nèi)容是有序列表,記錄了/etc/ld.so.conf配置文件(及/etc/ld.so.conf.d/*.conf 這些子配置文件)中指定的目錄,這些所有目錄下的動(dòng)態(tài)庫(kù)文件的有效信息。除了這些目錄,還包含了 通過(guò)命令行指定的目錄、以及系統(tǒng)必要的目錄 /lib、 /lib64 中的動(dòng)態(tài)庫(kù)文件信息。

/* Now dlibs contains a list of all libs - add those to the cache
     and created all symbolic links.  
     dlibs 包含了指定目錄下查找到的所有動(dòng)態(tài)庫(kù)信息。將用于添加到緩存,并創(chuàng)建軟鏈接(SONAME 文件)。
     */
  struct dlib_entry *dlib_ptr;
  for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
    {
      /* The cached file name is the soname for non-glibc-hwcaps
  subdirectories (relying on symbolic links; this helps with
  library updates that change the file name), and the actual
  file for glibc-hwcaps subdirectories.  
     /etc/ld.so.cache 文件的
     */
      const char *filename;
      if (entry->hwcaps == NULL)
 {
   /* Don t create links to links.  
      不創(chuàng)建指向鏈接文件的鏈接。
      */
   if (dlib_ptr->is_link == 0)
     create_links (dir_name, entry->path, dlib_ptr->name,
     dlib_ptr->soname);
   filename = dlib_ptr->soname;
 }
      else
 {
   /* Do not create links in glibc-hwcaps subdirectories, but
      still log the cache addition.  
         glibc 的 hwcaps 是2.33 版本開(kāi)始引入的功能,
         支持hwcaps意味著除了常規(guī)編譯的庫(kù)之外,現(xiàn)在還可以使用來(lái)自最新 CPU 
         的擴(kuò)展 cpu 指令集來(lái)安裝庫(kù),glibc 將自動(dòng)選擇針對(duì)當(dāng)前使用的
         cpu 優(yōu)化的版本。ldconfig對(duì)于glibc-hwcaps子目錄下的動(dòng)態(tài)庫(kù),
         不會(huì)創(chuàng)建對(duì)應(yīng)的SONAME,但仍會(huì)記錄記錄到/etc/ld.so.cache文件內(nèi)。
         以被Linux在運(yùn)行時(shí)按需使用。
         */
   if (opt_verbose)
     printf ("\t%s -> %s\n", dlib_ptr->soname, dlib_ptr->name);
   filename = dlib_ptr->name;
 }
      if (opt_build_cache)
 add_to_cache (entry->path, filename, dlib_ptr->soname,
        dlib_ptr->flag, dlib_ptr->osversion,
        dlib_ptr->isa_level, hwcap, entry->hwcaps);
    }

從上面代碼出現(xiàn)的hwcaps相關(guān)的處理,在此補(bǔ)充一下關(guān)于glibc-hwcaps的作用說(shuō)明 Hackweek 20: glibc-hwcaps in openSUSE[3];glibc-hwcaps 與AMD CPU的性能優(yōu)化的關(guān)系[4],指出glibc-hwcaps 是基礎(chǔ)設(shè)施的開(kāi)始,以便能夠更容易地根據(jù)硬件功能交付優(yōu)化的庫(kù)/共享對(duì)象。這是在庫(kù)級(jí)別,用于提供插入式優(yōu)化庫(kù),而不是 GCC 的 FMV(函數(shù)多版本控制)之類(lèi)的庫(kù),后者在構(gòu)建時(shí)試圖提供優(yōu)化的函數(shù),然后在運(yùn)行時(shí)根據(jù) CPU 主機(jī)進(jìn)行選擇。

以上代碼最后看到的 add_to_cache(……),的用法是這樣的:

add_to_cache (entry->path, filename, dlib_ptr->soname,
        dlib_ptr->flag, dlib_ptr->osversion,
        dlib_ptr->isa_level, hwcap, entry->hwcaps);

從名稱(chēng)上看,就是把 找到的一個(gè)動(dòng)態(tài)庫(kù)的記錄,添加到緩存數(shù)據(jù)結(jié)構(gòu)(鏈表)中。這個(gè)是在for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) 的for 每次循環(huán)過(guò)程的最后執(zhí)行的,也就是把有效的動(dòng)態(tài)庫(kù)信息添加到鏈表。

從上層看,概要的,ldconfig 生成緩存文件,有這樣的大體流程:

main() {……
    search_dirs (void)//獲取所有待查找的目錄列表
    {
      struct dir_entry *entry;
      for (entry = dir_entries; entry != NULL; entry = entry->next)
        search_dir (entry); // 進(jìn)入每個(gè)目錄,查找動(dòng)態(tài)庫(kù),并記錄到鏈表中
      } 
    }
     if (opt_build_cache)//若命令行參數(shù)要求生成緩存文件
    {
      save_cache (cache_file); //保存最終的緩存結(jié)果數(shù)據(jù)到 指定的緩存文件
                               //不指定文件路徑則默認(rèn)是/etc/ld.so.cache 文件。
      if (aux_cache_file)// aux_cache_file是輔助緩存文件。
     save_aux_cache (aux_cache_file);
      }
}

看一看這個(gè)流程,就對(duì)ldconfig如何將最新從/etc/ld.so.conf文件讀取的動(dòng)態(tài)庫(kù)目錄下的所有動(dòng)態(tài)庫(kù)的緩存信息,生成為/etc/ld.so.cache緩存文件,有了整體的認(rèn)識(shí)。

看完這些代碼,說(shuō)幾點(diǎn)印象:

  • 這些代碼考慮到很多方面,不是一次成型的,通過(guò)git提交記錄,以及changelog文件,我們看到Linux動(dòng)態(tài)庫(kù)的版本格式從glib4/5/6 有發(fā)展演化。
  • glibc 的ldconfig的代碼是C語(yǔ)言實(shí)現(xiàn)的,其生成的/etc/ld.so.cache緩存文件,對(duì)于Linux下的依賴(lài)動(dòng)態(tài)庫(kù)的可執(zhí)行文件的正常運(yùn)行,關(guān)系重大。所以為了優(yōu)化,和確保軟件更新后的穩(wěn)定性,會(huì)有一套命名標(biāo)準(zhǔn)。比如SONAME的命名機(jī)制。對(duì)軟鏈接是否有效的判斷,以及對(duì)新動(dòng)態(tài)庫(kù)的軟鏈接信息的更新。所以總體流程還是比較繁雜的。要考慮到的細(xì)節(jié)比較多。從git commit歷史看,代碼維護(hù)者的名稱(chēng)大部分是國(guó)外開(kāi)發(fā)者。
  • ldconfig 的C語(yǔ)言風(fēng)格有編碼排版約定,可讀性尚可。也做了模塊拆分(如 ldconfig的功能,劃分到了多個(gè)文件,如入口文件 ldconfig.c 、緩存的讀寫(xiě)邏輯實(shí)現(xiàn)文件 cache.c 、SONAME文件輔助功能文件readlib.c 、 chroot功能文件 chroot_canon.c )
  • ldconfig 的代碼存在的不足,也是很多C項(xiàng)目的問(wèn)題,使用了很多全局變量,各個(gè)函數(shù)到處在直接操作全局變量。雖然功能上沒(méi)問(wèn)題,高手寫(xiě)的代碼也不會(huì)有運(yùn)行異常,但總感覺(jué)可讀性和內(nèi)聚程度降低了。如果是我來(lái)實(shí)現(xiàn)ldcnfig,我會(huì)在內(nèi)聚性和代碼注釋方面做一些改進(jìn)。減少全局靜態(tài)變量的使用;改成main()內(nèi)部的變量,且通過(guò)main向被調(diào)用的函數(shù)傳參指針參數(shù)的方式傳入待讀寫(xiě)的變量。以此提高可讀性。

  • 部分函數(shù)的單函數(shù)代碼行數(shù)過(guò)長(zhǎng),比如search_dir(),還可以再拆分成多個(gè)函數(shù)。也是為了可讀性能好一些。
  • 部分關(guān)鍵結(jié)構(gòu)體的成員變量定義時(shí),沒(méi)有注釋說(shuō)明其作用。雖然通過(guò)看調(diào)用代碼能知道,但這樣的struct定義降低了可讀性。

總之,通過(guò)本系列文章對(duì)Linux 的ldconfig命令的源碼,從讀動(dòng)態(tài)緩存文件、打印庫(kù)緩存信息、查找/etc/ld.so.conf 指定的目錄的動(dòng)態(tài)庫(kù)信息等功能做了原理分析。希望對(duì)讀者理解ldconfig的原理些許幫助。

參考資料:

  • [1]ldconfig的代碼中,search_dir()函數(shù)的關(guān)鍵內(nèi)容: https://sourceware.org/git?p=glibc.git;a=blob;f=elf/ldconfig.c;h=bccd386761d8cbb226bd3b02c17bf55cd552cee4;hb=HEAD#l702
  • [2]ldconfig的幫助文檔: https://www.man7.org/linux/man-pages/man8/ldconfig.8.html
  • [3]Hackweek 20: glibc-hwcaps in openSUSE: https://antlarr.io/tag/glibc-hwcaps/
  • [4]glibc-hwcaps 與AMD CPU的性能優(yōu)化的關(guān)系: https://www.phoronix.com/news/glibc-hwcaps-RFC
責(zé)任編輯:趙寧寧 來(lái)源: 深入理解Linux
相關(guān)推薦

2009-11-25 10:08:56

ldconfig命令linux

2023-12-25 16:10:34

Linuxdconfig命令

2020-05-15 07:00:00

Linux硬盤(pán)信息

2023-03-21 09:31:30

Linux命令行文件夾

2012-12-28 14:28:26

Android開(kāi)發(fā)

2015-06-08 16:42:52

linux運(yùn)維

2023-03-15 10:34:47

Linux文件數(shù)

2009-08-03 12:09:42

linux at命令linux at命令詳batch

2018-03-30 17:51:17

Linux命令查找文件

2022-10-25 13:01:36

Linux命令行空目錄

2022-11-02 08:20:43

Linux

2021-12-12 09:19:16

find命令Linux

2010-01-06 11:24:27

Linux命令

2023-12-20 13:49:00

Linux動(dòng)態(tài)庫(kù)代碼

2022-03-24 23:04:37

linux靜態(tài)庫(kù)動(dòng)態(tài)庫(kù)

2015-09-02 15:47:05

命令行fdupesLinux

2010-01-11 10:05:18

Linux刪除目錄

2022-09-27 10:07:01

要使用 source

2018-04-28 09:12:42

Linux

2022-05-25 08:41:48

Linuxfd 命令文件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产在线永久免费 | 婷婷国产一区 | 国产午夜精品一区二区三区四区 | 免费观看成人鲁鲁鲁鲁鲁视频 | 亚洲在线看 | 免费在线观看一级毛片 | 久久久夜色精品亚洲 | 亚洲免费人成在线视频观看 | 日韩午夜精品 | 中文字幕视频三区 | 中文字幕第一页在线 | 国产精品久久久久久一区二区三区 | 日韩欧美在线免费 | 久久伊人一区二区 | 久久成人在线视频 | 亚洲www| 国产成人一区二区三区电影 | 国产欧美精品区一区二区三区 | 新91视频网 | 91精品国产高清一区二区三区 | 久久久久国产一区二区三区四区 | 九九热精品视频 | 日韩午夜在线播放 | 在线欧美视频 | 欧美国产精品一区二区三区 | 国产高清视频一区 | 国产精品久久久久久二区 | 免费观看色 | 久久亚洲欧美日韩精品专区 | 日韩成人在线免费视频 | 日韩在线一区二区 | 91在线一区| 欧美精品在线视频 | 久久99国产精品 | 亚洲综合热 | 国产一区二区在线免费视频 | 精品久久久一区 | www.啪啪.com| 在线观看的av | 亚洲成人免费 | 欧美一区视频 |