ファイル形式を読み取ろうとしています/dev/null
。使用するとstat()
文字デバイスと正確に報告されます。
を使用すると、getdents()
文字デバイスと報告されます。コンテナで実行しない限り、通常のファイルと表示されます。
コンテナで実行すると、なぜ他の結果が出るのですか?
この画像を使用してdockerとpodmanの最新バージョンでテストした結果は同じでしたubuntu:22.04
。
コピーするコードは次のとおりです。このコードはstat()
常に機能しますが、getdents
コンテナ内で実行するとアサーションが失敗します。また、注目すべき点は、コードが常にコピーされるわけではないことです。一部のシステム/コンテナではまだうまく機能しているようです。
(Linux 6.8.2-arch2-1およびpodman 5.0.0でテスト済み)
#include <assert.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#define BUF_SIZE 1024
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
int main() {
// stat approach
struct stat st;
stat("/dev/null", &st);
printf("stat type: %d\n", st.st_mode & S_IFMT);
assert((st.st_mode & S_IFMT) == S_IFCHR);
// getdirents approach
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
fd = open("/dev", O_RDONLY | O_DIRECTORY);
for (;;) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *)(buf + bpos);
if (strcmp(d->d_name, "null") == 0) {
d_type = *(buf + bpos + d->d_reclen - 1);
printf("getdents type: %d\n", d_type);
assert(d_type == DT_CHR);
exit(EXIT_SUCCESS);
}
bpos += d->d_reclen;
}
}
close(fd);
exit(EXIT_SUCCESS);
}
答え1
getdirents
これがあなたに話す真実であることがわかりました!
ルートなしのpodmanコンテナに移動して実行すると、これが実際にバインドマウントであることがmount
わかります(コンテナ内のサンプルコードにアクセスできるようにここにあります)。/dev/null
-v ...
$ podman run -it --rm -v $PWD:/src:z fedora:39
[root@00af7efc8781 /]# mount |grep /dev/null
devtmpfs on /dev/null type devtmpfs (rw,nosuid,noexec,seclabel,size=4096k,nr_inodes=8186582,mode=755,inode64)
このバンドルのインストールを削除すると、何が表示されますか?調べましょう:
まずコンテナpidが必要です。
$ podman container inspect -l | jq .[0].State.Pid 50502
これにより、
nsenter
関連するmountとpidの名前空間を入力できます。$ sudo nsenter -t 50502 -m -p
/dev/null
最後に、バインドマウントを削除できます。[root@fizzgig /]# umount /dev/null
これで、次のことがわかります。
[root@fizzgig /]# ls -l /dev/null
-rwx------. 1 21937 21937 0 Apr 2 20:03 /dev/null
驚くべきことに、これはファイルです!
呼び出しはgetdirents
ディレクトリエントリから読み込み中です/dev
。これは、バインドマウントについて知らないことを意味するため、d_type
基本項目が表示されます。