Linux のリンク解除機能とファイルの削除方法

Linux のリンク解除機能とファイルの削除方法

1. リンク解除機能

ハード リンクの場合、unlink はディレクトリ エントリを削除し、inode 参照カウントを 1 減らすために使用されます。これら 2 つの手順もアトミック プロセスです。 inode 参照カウントが 0 に達するまで、ファイルは実際には削除されません。

ソフト リンクの場合、unlink はソフト リンクが指すファイルに影響を与えずにソフト リンクを直接削除します。

関数プロトタイプ:

int unlink(const char *pathname);

パラメータの説明:

パス名: 削除するリンクファイルを指定します

戻り値の説明:

成功した場合は 0 を返し、失敗した場合は -1 を返し、errno を対応する値に設定します。

2. 実験コード—myunlink

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]){ 
 //既存のファイルのディレクトリエントリ(ハードリンク)を作成する
 (link(argv[1], argv[2]) == -1)の場合{
 perror("リンクエラー");
 終了(1);
 }
 // 以前のファイルディレクトリエントリを削除します if (unlink (argv [1]) == -1) {
 perror("リンク解除エラー");
 終了(1);
 }
 0を返します。
}

./myunlink hellotest コマンドを実行すると、hellotest が削除され、inode 参照カウントが 1 減少します。

3. ファイルを削除する

言うまでもなく、誰もが rm -rf コマンドを使用したことがあると思います。

さて、もう一度考えてみましょう。以前、rm コマンドを使用してファイルを削除したとき、ファイルが本当に削除されたのか疑問に思ったことはありませんか?

削除できる場合、オペレーティング システムはどのようにしてファイルを削除するのでしょうか?

オペレーティング システムが設計されるときに、ファイルの inode インデックス番号がディスク内のブロックに関連付けられ、ファイルを通じてブロックの場所を見つけて、ファイルのデータを確認できるようになります。

ファイルを削除するときは、ファイルへのハードリンクの数を示す i_link と、ファイルの参照カウントを示す i_count という 2 つのシステム変数によって制御されます。ファイル削除に必要な条件は、i_link = 0 および i_count = 0 です。

ディスク上のファイルの場合、ファイルを削除するには i_link = 0 (ハードリンクの数をクリア) を設定するだけです。ファイルがプログラムで開かれている場合は、ファイルを削除する目的を達成するために、実行中のプログラムの i_count = 0 もクリアする必要があります。

4. Linuxでファイルを削除する一般的な手順

Linux でのファイル削除プロセスは、おおよそ次のようになります。

這里寫圖片描述

図1- Linuxでのファイル削除の一般的なプロセス

現在のディスクの /test/file ディレクトリにテスト ファイルがあり (i_link = 1)、テスト ファイルを指すハード リンク ファイル hard_link があり (i_link = 1)、./test プロセスがテスト ファイルを開いています (i_count = 1)。test.txt ファイルを削除する場合は、./test プロセスを強制終了し (i_count = 0)、次に /test/file ディレクトリの hard_link ハード リンク ファイルと test.txt ファイルを削除する必要があります (つまり、i_link = 0 にします)。

つまり、Linux では、ファイルの削除はリンクの数によって制御されます。ファイルのリンクが 0 の場合、ファイルは削除されます。通常、ファイルには i_link と i_count の 2 つのリンク カウンターがあります。

i_count は現在のプロセスによって開かれたファイルの参照カウントであり、 i_link はファイルリンクの数です。 i_count はメモリ内のファイルのカウンターとして理解でき、 i_link はディスク内のカウンターです。 rm コマンドの場合、実際にはディスク上のファイルの i_link カウントが 0 に設定されます。プロセスがファイルを使用していて、ユーザーが rm コマンドを実行してファイルを削除しても、プログラムは正常に実行され、ファイルから正しいデータを読み取ることができます。これは、rm コマンドが i_link を 0 に設定するだけであるためです (ファイルと inode の関連付けが切断され、inode とディスク上のブロック データ ブロックは削除されません。この時点でプロセスが停止すると、削除されたデータを取得できます。プロセスがデータを書き込んでいる場合、ディスク ブロック内のデータはプロセスによって書き込まれたデータによって上書きされ、元のデータを回復することはできません)。

プロセスは、まだファイル i_count = 1 を参照しています。rm コマンドを実行しても、ファイルは実際には削除されません。ファイルを削除する場合は、プロセスにファイルの参照カウントを解放させる、つまりプロセスを強制終了させて​​、ファイルが本当に削除されるようにする必要があります。

それでも、ファイルは本当に削除されるのでしょうか?ファイルのデータはディスク上のブロックに保存されると前に説明しました。ファイル内のデータを探す場合、ディスク上のブロックが多すぎるため、ディスク上のブロックを直接探すことはできません。データがどのブロックに保存されているかはどうすればわかるのでしょうか。

非常に重要なデータを誤って削除した場合、そのデータは回復不可能となり、修復不可能な損失が発生します。これはデータの重要性を示すため、オペレーティング システムはディスクからデータを簡単に削除しません。

これを見ると、いわゆる右クリック削除操作では、実際にはファイルの inode インデックス番号がディスク上のブロックから切り離されるだけで、ファイル データは実際には削除されないことがおわかりいただけたと思います。本当にデータを削除したい場合は、ディスクをフォーマットするか、元のデータを削除してから新しいデータを書き込んで上書きすることができます。もちろん、二重の保険としてデータをフォーマットして上書きすることもできます。現時点では、データを回復するのは基本的に非常に困難であり、回復できたとしても、せいぜいデータの一部しか回復できません。

本当に誤って非常に重要なデータを削除してしまった場合は、データ回復プロセス中のデータ損失を最小限に抑えるために、すぐにデータを復元し、その他の不要な操作を行わないようにしてください。

5. myunlink2.c プログラム

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <文字列.h>
#include <stdio.h>
 /*
 unlink関数はdentryを削除します
 */
int main(void){
 整数データ;
 char *p = "リンク解除のテスト\n";
 char *p2 = "何かを書いた後\n";
 //プロセスがtemp.txtファイルを開くと、参照カウントは+1になります
 fd = open("temp.txt", O_RDWR|O_CREAT|O_TRUNC, 0644);
 (fd < 0)の場合{
 perror("オープン温度エラー");
 終了(1);
 }
 //解放される条件が満たされている int ret = unlink("temp.txt"); 
 if(ret < 0){
 perror("リンク解除エラー");
 終了(1);
 }
 //最初の文字列を temp.txt ファイルに書き込み、戻り値によって書き込み操作が成功したかどうかを判断します。ret = write(fd, p, strlen(p));
 戻り値が -1 の場合
 perror("-----書き込みエラー");
 }
 printf("こんにちは!私はprintfです\n");
 // 2 番目の文字列を temp.txt ファイルに書き込み、戻り値によって書き込み操作が成功したかどうかを判断します。ret = write(fd, p2, strlen(p2));
 戻り値が -1 の場合
 perror("-----書き込みエラー");
 }
 printf("任意のキーを押して続行\n");
getchar();
 //close が fd を閉じると、プロセスのファイルへの参照カウントは -1 になり、プロセスはファイルから切断されます close(fd);
 0を返します。
}

プログラム実行結果:

這里寫圖片描述

プログラムの結果は予想通りです。プログラムの実行中、open 関数が呼び出され、temp.txt ファイルが作成されて開かれます。このとき、プロセスの temp ファイルへの参照カウント i_count が 1 増加し、temp ファイル自体の i_link リンク カウントも 1 増加します。

unlink 関数を呼び出して一時ファイルを削除すると、i_link リンクカウントのみが 1 減少しますが、プロセスの i_count カウントは 1 のままで、一時ファイルとの関連付けは切断されません。したがって、プロセスは write 関数を呼び出して一時ファイルにデータを書き込むことができ、当然成功します。プログラムが終了すると、close を呼び出して一時ファイルへの参照を閉じます。一時ファイルはオペレーティング システムによって削除されます。

6. 結論

ファイルシステムの原理を理解していないと、通常、データが削除されたと考えてしまいます。実際には、ディスク上のファイルデータはまだ残っていますが、dentryディレクトリとディスク上のデータ間の接続は切断されています。データが見つからない場合は、間違いなく削除されたと考えます。ただし、データとdentryディレクトリ間の接続を再確立する方法を見つければ、削除されたデータを回復できます。

したがって、ファイルを削除するということは、ある意味では、ファイルを解放する準備をしているだけです。いつ解放されるかは、オペレーティング システムによって異なります。

unlink 機能では、ファイルをクリアするときに、ファイルのハードリンク数が 0 になり、対応する dentry がない場合、ファイルはすぐに解放されません。ファイルを開いたすべてのプロセスがファイルを閉じるまで、システムはファイルを解放しません。

7. rmコマンドを気軽に使用しない

これを読んでいただければ、コンピュータにとってデータがどれほど重要であるかがおわかりいただけると思います。重要なデータが削除されると、それは本当に永久に失われてしまうからです。オペレーティング システムがディスクからデータを直接削除しないのは、このためです。しかし、削除されたデータが完全に復元されない場合もあるため、rm コマンドを無謀に使用してもよいということではありません。

要約する

以上、Linuxのunlink機能とエディタで紹介したファイル削除の操作方法でした。皆様のお役に立てれば幸いです。123WORDPRESS.COMサイトを今後ともよろしくお願いいたします!

以下もご興味があるかもしれません:
  • Linuxのアラーム機能の例の説明
  • PHP は 6 つの Linux コマンド関数コード例を実行します
  • Linux での stat 関数と stat コマンドの使用法の詳細な説明
  • Linux で time(NULL) 関数と localtime() を使用して現在の時刻を取得する方法
  • Linux/Mac で Python 関数にタイムアウトを追加する方法
  • Linux lseek関数の使い方の詳しい説明
  • ARMアーキテクチャにおける関数呼び出しプロセスの簡単な分析

<<:  MySQLの共有ロックと排他ロックの使用例の分析

>>:  ECMAScriptにおけるプリミティブ値と参照値の詳しい説明

推薦する

Dockerはコード検出プラットフォームSonarQubeを構築し、Mavenプロジェクトのプロセスを検出します

1 はじめに優れたコーディング習慣は優れたプログラマーが備えるべき資質ですが、コードの品質を保証する...

Linuxコマンドをバックグラウンドで実行する方法

通常、ターミナルでコマンドを実行する場合、別のコマンドの入力を開始する前に、現在のコマンドが終了する...

http:// の代わりに // を使用する利点は何ですか (アダプティブ https)

//デフォルトプロトコル/ デフォルト プロトコルの使用は、リソース アクセス プロトコルが現在の...

DockerプライベートライブラリHarborのアーキテクチャとコンポーネントの説明

この記事では、Harbor アーキテクチャの構成と、実行時に各コンポーネントを使用する方法について説...

js キャンバスは角丸画像を実現します

この記事では、角を丸くするためのjsキャンバスの具体的なコードを参考までに紹介します。具体的な内容は...

js の通常形式の日付と時刻に 0 を自動的に追加する 2 つのソリューション

目次背景解決策1アイデア:コード:解決策2アイデア:要約する参照する背景日付と時間をフォーマットする...

MySQLデータベースのnullに関する知識ポイントのまとめ

MySQL データベースでは、null は一般的な状況です。MySQL での null に関する注意...

CSS スタイルを使用して表のフォントを垂直中央に配置する方法

CSS スタイルを使用して表内のフォントを垂直方向に中央揃えする方法は次のとおりです。下図のようなカ...

Tomcatの各ポートの機能の詳細な説明

tomcat 設定ファイルから、tomcat の起動時にデフォルトで 8080 (8443)、800...

WeChatアプレット学習ノート: ページ構成とルーティング

最近、小さなプログラムの開発を勉強して見直しており、学習結果のいくつかをメモしています。公式の We...

カーソル ループを使用して、MySQL ストアド プロシージャで一時テーブルを読み取る

カーソルカーソルは、結果セット内のデータを表示または処理するために使用される方法です。カーソルを使用...

初心者がdockerにmysqlをインストールするときに遭遇するさまざまな問題

序文最近、パソコンのシャットダウンに時間がかかることが多く、強制的にシャットダウンするには電源ボタン...

Ubuntu 18.04にPython仮想環境をインストールする

Ubuntu 18.04 を使用する Python 開発者向けの参考資料です。 1. Ubuntu ...

MySQL MHA の高可用性構成とフェイルオーバーの詳細な導入手順

目次1. MHAの紹介1. MHAとは何ですか? 2. MHAの構成3. MHAの特徴2. MySQ...

ローカルサーバーを構築するためのwebpack-dev-serverの実装

目次序文webpack-deb サーバーwebpack-dev-server 起動エラー解決策1解決...