2015-06-01 20 views
1

我陷入了一個奇怪的問題。Linux:在運行時設置語言環境和進程間依賴關係

我有兩個腳本(C程序的可執行文件)ARM的Linux機器被安裝在兩個不同的路徑相同的USB設備(含有中國字符的文件名),只要該裝置插入上運行。

int mount(const char *source, const char *target, 
       const char *filesystemtype, unsigned long mountflags, 
       const void *data); 

在最後一個參數, 腳本A通過「UTF8」和腳本B通過0

所以,當我插入USB設備,腳本比賽來安裝設備。

如果腳本A安裝第一(其中通過UTF8參數),我得到正確的文件名。這是mount命令的輸出[注意,即使第二個mount沒有通過,第二個mount也有utf8作爲參數。爲什麼?]

/dev/sdb1 on /home/root/script1 type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-r 
o) 
/dev/sdb1 on /home/root/script2 type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed 
,utf8,errors=remount-ro) 

但如果腳本B座第(其中通過0作爲最後一個參數來安裝),我得到碎文件名?????.mp3readdir()。這是mount命令的輸出。

/dev/sdb1 on /home/root/script2 type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro) 
/dev/sdb1 on /home/root/script1 type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed 
,errors=remount-ro)   

編輯

這無論是對開發測試腳本的基本安裝代碼(僅在最後一個掛載參數差異)。這兩個腳本在使用服務重新啓動時立即執行。

//mount the device 
     ret = mount("/dev/sda1", "/home/root/script1/", "vfat", 1, "utf8"); 
     if (ret == 0) { 
       fprintf(stdout,"mount() succeeded.\n"); 
       sleep(2000); 
     } else { 
       ret = mount("/dev/sdb1", "/home/root/script1/", "vfat", 1, "utf8"); 
       if(ret == 0) 
       { 
        fprintf(stdout,"mount() succeeded\n"); 
        sleep(2000); 
       } 
       else 
       { 
        fprintf(stdout,"/dev/sdb1 mount() failed: %d, %s\n", errno, strerror(errno)); 
        ret = mount("/dev/sdc1", "/home/root/script1/", "vfat", 1, "utf8"); 
        if(ret == 0) 
        { 
         fprintf(stdout,"mount() succeeded\n"); 
         sleep(2000); 
        } 
        else 
         fprintf(stdout,"mount() failed: %d, %s\n", errno, strerror(errno)); 
       } 
     } 
+0

Pure C,如果它很重要。編輯了這個問題。 –

+0

所以問題在於腳本A和腳本B之間的競爭條件。它如何與c語言環境和C相關? – myaut

+0

只要我們沒有看到mount命令,我們就不能告訴你爲什麼腳本2失敗。請發佈script2的代碼 – Nidhoegger

回答

3

一般來說,你應該永遠兩次安裝同一個文件系統 - 如果OS驅動程序將決定兩次寫入相同的塊,你會得到文件系統損壞。在這種情況下使用綁定掛載。

然而,Linux足夠聰明地幫助你 - 它將重新使用舊的文件系統掛載super_block(帶有所有掛載點標誌)作爲一個位置。

我找不到它的文件,但它是通過在sget()內核源代碼是由mount_bdev()稱爲溯源:

hlist_for_each_entry(old, &type->fs_supers, s_instances) { 
     if (!test(old, data)) 
       continue; 
     if (!grab_super(old)) 
       goto retry; 
     if (s) { 
       up_write(&s->s_umount); 
       destroy_super(s); 
       s = NULL; 
     } 
     return old; 
} 

在這個片段中,它會尋找對應於的super_block以前的實例塊設備,如果它已經存在 - 只需返回它。


一些實際使用證明了SystemTap:

# stap -e 'probe kernel.function("sget").return { 
     sb = $return; 
     active = @cast(sb, "super_block")->s_active->counter; 
     fsi = @cast(sb, "super_block")->s_fs_info; 
     uid = fsi == 0 ? -1 
      : @cast(fsi, "msdos_sb_info", "vfat")->options->fs_uid; 
     printf("%p active=%d uid=%d\n", sb, active, uid); 
    }' 

在第二底座設置UID不改變選項,但會增加主動底座的數量(明顯):

# mount /dev/sdd1 /tmp/mnt1 
    0xffff8803ce87e800 active=1 uid=-1 
    # mount -o uid=1000 /dev/sdd1 /tmp/mnt2 
    0xffff8803ce87e800 active=2 uid=0 

在安裝逆序還繼承了安裝選項:

# mount -o uid=1000 /dev/sdd1 /tmp/mnt2 
    0xffff8803cc609c00 active=1 uid=-1 
    # mount /dev/sdd1 /tmp/mnt1 
    0xffff8803cc609c00 active=2 uid=1000 

如果你想知道誰是負責這樣的行爲,要求萊納斯,similiar代碼存在,因爲0.11:

struct super_block * get_super(int dev) 
{ 
    struct super_block * s; 

    if (!dev) 
     return NULL; 
    s = 0+super_block; 
    while (s < NR_SUPER+super_block) 
     if (s->s_dev == dev) { 
      wait_on_super(s); 
      if (s->s_dev == dev) 
       return s; 
      s = 0+super_block; 
     } else 
      s++; 
    return NULL; 
} 

(但是當這種代碼是負責,sys_mount()明確檢查,沒有其他的掛載點存在爲那個超級塊)。

您可以嘗試在LKML上提問。

相關問題