コマンドの実現のプログラミングLinuxのシステム

私たちは、あなたがより自分の習慣(もちろん、一般的なLinuxコマンドに適し書かれたコマンドを使用できることを意味し、既存の秩序を向上させることができ、様々なプログラムを実装するために練習のLinuxシステムのプログラミングでは、実際にそれを理解する必要がありますより包括的な、そのトラブルがショートカットを使用してパラメータ)と命名されている可能性が、あなたは特定見ることができます議論Linux環境変数を

誰を理解します

コマンドは、現在のシステム情報にログインしているユーザーが表示されます。誰が、ログインアカウントの端末の使用をコマンドリストを実行し、符号どこの時間にログインします。

任意のコマンドを書くための書き込みは、あなたが最初にそれを理解する必要があり、最良の方法はどのようなパラメータを詳細に見てする必要はありません何を、私たちはこのことに注意する必要があります、コマンドが実装されている方法を理解する必要があります$男、マニュアルを読むことです文:

FILEが指定されていない場合は、使用には/ var / run / utmp。FILEとしては/ var / log / wtmpのが一般的です。

ファイルが指定されていない場合には、最終的にはutmp何の下で検索し、whoコマンドとのwtmpファイルを完成ヘルプを一緒にWTMP、読むためには/ var / run / utmpファイルから、あるある、あなたは私たちに沿った検索がある見ることができます条件。

xxx@xxx-ThinkPad-X230-Tablet:/var/run$ man -k utmp
utmp (5)             - login records

我々は明確にutmpファイルを理解することができ、このファイルの男5のutmp $の役割を開き、私たちは次のことを知っておく必要がある部分を選択します。

DESCRIPTION
       The  utmp file allows one to discover information about who is currently using the system.  There may be more users currently using the system, because not all programs use utmp logging.
       Warning: utmp must not be writable by the user class "other", because many system programs (foolishly)  depend  on  its  integrity.
       You  risk  faked  system logfiles and modifications of system files if you leave utmp writable to any user other than the owner and group owner of the file.
       The file is a sequence of utmp structures, declared as follows in <utmp.h> (note that this  is  only  one  of  several  definitions around; details depend on the version of libc)
       The  wtmp  file  records all logins and logouts.  Its format is exactly like utmp except that a null username indicates a logout on the associated terminal.  

説明のutmp段落はここで見ることができ、すべてのログインとログアウトの情報についてのwtmpファイルによると、システムの現在使用中の情報を読み出すことができます。

小さなエピソードが、私はこれはそれハッハッハ悪い気分の1の方法で自分自身を表現するために、著者やユーザーの交換で感じることができ、ここで、著者とまだ愚か愚かさの整合性に依存しているシステムプログラムの多くを表現しているがあります。

ここでは、注文utmpファイルに実装直接法コードは、データ構造を定義し、utmp.hはそれだけでは一方で、文のすべてが含まれた後、ステートメントutmp.hに含めるファイルを表示して取得するために私たちに語りました以前のバージョンを比較し、それは全てのデータ構造のutmp.hで定義され、umptは、アレイの構成のみを保存し、データ要素は、構造体のutmpのタイプであり、utmpファイルに相当する、のutmp utmp.hクエリのタイプを定義することが必要ですファイルはちょうどクエリエントリ、私はそれだと思う。この理由の現在に新しいバージョンです。

  • コンパイラは、時間コンパイラ保存、保存して効率を改善するための構造のバックの種類utmp.hを行くために必要なファイルをコンパイルする必要はありませんので、直接格納されたデータ構造のようなタイプで、時間を節約、直接定義。

また見つかった、ドキュメントのいくつかのutmp.h概要はカーネル関数に導入され、そのパッケージを介してユーザモードの関数宣言。utmpのログイン情報が保存され、彼は情報を保存したが、カーネル関数のパッケージを介して行わutmp.hの呼び出しを介して行われ、それはutmpファイルに戻っています。私たちは誰のコマンドを実行し、その後はutmpからログイン情報を取得する場合。

 struct utmp {
               short   ut_type;              /* Type of record */
               pid_t   ut_pid;               /* PID of login process */
               char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
               char    ut_id[4];             /* Terminal name suffix,
                                                or inittab(5) ID */
               char    ut_user[UT_NAMESIZE]; /* Username */
               char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
                                                kernel version for run-level
                                                messages */
               struct  exit_status ut_exit;  /* Exit status of a process
                                                marked as DEAD_PROCESS; not
                                                used by Linux init (1 */
               /* The ut_session and ut_tv fields must be the same size when
                  compiled 32- and 64-bit.  This allows data files and shared
                  memory to be shared between 32- and 64-bit applications. */
           #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
               int32_t ut_session;           /* Session ID (getsid(2)),
                                                used for windowing */
               struct {
                   int32_t tv_sec;           /* Seconds */
                   int32_t tv_usec;          /* Microseconds */
               } ut_tv;                      /* Time entry was made */
           #else
                long   ut_session;           /* Session ID */
                struct timeval ut_tv;        /* Time entry was made */
           #endif

               int32_t ut_addr_v6[4];        /* Internet address of remote
                                                host; IPv4 address uses
                                                just ut_addr_v6[0] */
               char __unused[20];            /* Reserved for future use */
           };

ノートの裏にも明確に上陸の種類を含め、それを保存するこの構造を理解することができますから、これは、定義はutmp構造であり、かつその上にID、PIDログを上陸させました。

私たちは誰のコマンドを達成したいので、次のステップは、読み出されて表示された1つによって、ユーザーレコードのいずれかにログインすることです。

誰が書き込み

解決すべき第一の問題は、2つの方法を考え、データ構造のファイルを読み込む方法です。

  • ダイレクト印刷GETC、次に関数fgetsで文字列を読み出します

    しかし、これは明らかに非常に非効率的なアプローチ

今回は近く、読み、オープンすなわち、ファイル操作を考えました。データ構造を保持している私たちのアイデアは、バッファに書き込まれたファイルにあるので、データ構造は、その後することができ、印刷に保存されています。

主な機能を見てください

  1 #include <stdio.h>
  2 #include <utmp.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include "show_info.c"
  6 
  7 #define SHOWOST
  8 
  9 int main()
 10 {
 11         struct utmp current_record;
 12         int utmpfd;
 13         int reclen = sizeof(current_record);
 14 
 15         if((utmpfd = open(UTMP_FILE,O_RDONLY))==-1)
 16         {
 17                 perror(UTMP_FILE);
 18                 exit(1);
 19         }
 20 
 21         while (read(utmpfd,&current_record,reclen)==reclen)
 22         show_info(&current_record);
 23         close(utmpfd);
 24         return 0;
 25 
 26 }

show_infoログイン情報を表示ここで読み取られたデータを保持し、データの各タイプをutmpのを読んで、読んで、そして最終的に機能を呼び出すために継続して構造体のutmpのタイプを使用しています。show_info非常にシンプルな構造、データの構造のみのように保存された読み取りを継続するために使用する必要があります。

  1 show_info(struct utmp *utbufp){
  2         printf("%-8.8s",utbufp->ut_name);
  3         printf(" ");
  4         printf("%-8.8s",utbufp->ut_line);
  5         printf(" ");
  6         printf("%10ld",utbufp->ut_time);
  7         printf(" ");
  8 #ifdef SHOWOST
  9         printf("(%s)",utbufp->ut_host);
 10 #endif  
 11         printf("\n");
 12 }       

コード自体は主にそれがどのように動作するかを見つけるとプロセスに、比較的簡単であり、そしてどのようにあなたはそれが書き込み処理を考慮していると思います、私はここにヘッダファイルや機能別々の道を選んだ、そこにいくつかの問題となっているが、幸い、最終的に解決されて詳細については、ヘッダファイルに定義され、分離された処理機能を

これにより、出力を実行されています:

xxx@xxx-ThinkPad-X230-Tablet:~/code/unix_linux/who$ ./a.out 
reboot   ~        1540433259 (4.15.0-34-generic)
runlevel ~        1540433270 (4.15.0-34-generic)
xxx      :0       1540433375 (:0)
LOGIN    tty3     1540979878 ()

そして、システムのコントラスト者:

xxx@xxx-ThinkPad-X230-Tablet:~/code/unix_linux/who$ who
xxx      :0           2018-10-25 10:09 (:0)

2つの欠点があります。

  • これは、ログに記録されたレコードを排除するが、それらをすべて印刷されません。
  • 時刻を正しく表示されません

この問題を解決します

ログインレコードの除去

第一の問題は、システムがユーザ端末はそれを区別アクティビティに対応する方法であることを考慮に入れる最初のテイクを解決するには?私たちは、各ユーザーのシステムは、識別子を与えたことがわかった、utmpのビューに戻ります。

           #define EMPTY         0 /* Record does not contain valid info
                                      (formerly known as UT_UNKNOWN on Linux) */
           #define RUN_LVL       1 /* Change in system run-level (see
                                      init(8)) */
           #define BOOT_TIME     2 /* Time of system boot (in ut_tv) */
           #define NEW_TIME      3 /* Time after system clock change
                                      (in ut_tv) */
           #define OLD_TIME      4 /* Time before system clock change
                                      (in ut_tv) */
           #define INIT_PROCESS  5 /* Process spawned by init(8) */
           #define LOGIN_PROCESS 6 /* Session leader process for user login */
           #define USER_PROCESS  7 /* Normal process */
           #define DEAD_PROCESS  8 /* Terminated process */
           #define ACCOUNTING    9 /* Not implemented */

それが唯一の関数の出力show_info前に、差別などの条件を持っている必要がありますので、だから我々は必要なもの、7である識別子、通常のユーザーであります:

if(utbufp->type!=USER_PROCESS)
return;

そして、それを実行し、最初の問題は解決されます。

xxx@xxx-ThinkPad-X230-Tablet:~/code/unix_linux/who$ ./a.out 
xxx      :0       1540433375 (:0)

ショータイム

我々は最初のLinuxの蓄積時間は、時間は、Linuxの下に二つの記憶に分かれている方法を理解する必要があり、時間を取得する必要があります。

  • 秒数後に、今まで1970年からストレージの使用time_tのタイプ
  • tm構造体の日付を使用すると、毎分格納されている場合、ニーズが年ではなく、直接、現在の年間保存するよりも、長年にわたって存在に1900年からであることは注目に値します。

時間関連の文書による方法を見つけると私たちは答えを見つけたい人3のctimeによって、関連するオープンを発見したため、または老人-k時間:

 The call ctime(t) is equivalent to asctime(localtime(t)).  It converts the calendar time t into a  null-terminated  string  of  the form

          "Wed Jun 30 21:49:08 1993\n"

これは、毎日の時間フォーマットを変換するためのtime_tのctime関数の値と、第一の方法を使用して提示されなければなりません。CTIME機能もノートで、このドキュメントの使用に関連しています:

char *ctime(const time_t *timep);

そして、最初のアプローチを使用し、CTIMEので、4番目の文字の統計から始まる、ここで我々は必要としない週、上記のように時刻文字列を返す、time_t型へのポインタがあるでしょう。

私たちは、ショータイム機能を追加する必要があります。

  1 #include <stdio.h>
  2 #include <utmp.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include "show_info.h"
  6 #include <time.h>
  7 void showtime(long timeval)
  8 {
  9         char *cp;
 10         cp = ctime(&timeval);
 11         printf("%12.12s",cp+4);
 12 }           

あなたが最終的に変更して、show_infoパートタイム内の出力を交換する必要が最終的な結果を得たと同時に、出力にはしようとします:

xxx@xxx-ThinkPad-X230-Tablet:~/code/unix_linux/who$ ./a.out 
xxx      :0       Oct 25 10:09(:0)

システムの比較:

xxx@xxx-ThinkPad-X230-Tablet:~/code/unix_linux/who$ who
xxx      :0           2018-10-25 10:09 (:0)

異なるフォーマットの完全な実現に加えて!

私たちは、それが一緒に文字列、その過程で多くのことを学ぶか、詳細には、非常に興味深い行くことができる可能性があり、それがどのように動作するかを理解し、通話を実現するためにどのような機能、それが定義されている方法のためのマニュアルを見て、見にソースからの書き込みコマンドに必要。

公開された15元の記事 ウォン称賛13 ビュー9060

おすすめ

転載: blog.csdn.net/weixin_43122409/article/details/83963882