C/C++処理の超徹底解説【後編】(体系学習day07)

目次

序文

1. デーモンプロセス

1.コンセプト

2. デーモンプロセス作成の原理 (図ではっきりと確認できます)

 3. デーモンプロセスの実装(コードブロック)

2.dupとdup2

1. ファイル記述子のコピー

2. ファイル記述子のリダイレクト

3. システムログ

1. ログを開く

2. メッセージをログに書き込みます

3. ログを閉じます

4. ファイルロック

1.コンセプト

2. ファイル全体をロックする

コード例は次のとおりです。 

3. ファイルの特定の領域をロックします

 コード例は次のとおりです。

5. プロセス間通信

1. 分類

2. 名前のないパイプ

2.1 匿名パイプ通信の原理

2.2 使用法

 コード例は次のとおりです。

要約する


序文

前回のブログではC/C++の処理の上部を詳しく解説しましたが、今回はスレッドに関する知識の補足と解説を続けていきます。


1. デーモンプロセス

1.コンセプト

(1) デーモン プロセス (
    デーモン プロセスとも呼ばれる) は、Linux のバックグラウンド サービス プロセスです。
    これは、寿命が長いプロセスであり、通常は制御端末から独立しており、定期的に特定のタスクを実行するか、発生する特定のイベントの処理を待機します。多くの場合、デーモン プロセスは、システムがブートおよびロードされるときに開始され、システムが起動されると終了します
    。
    Linux システムには多くのデーモンがあり、ほとんどのサービスはデーモンを使用して実装されてい ます

(2) ターミナル
    Linux では、各システムが利用者と通信するためのインターフェースをターミナルと呼び、このターミナルから実行を開始するプロセスはすべてこのターミナルに接続され、このターミナルをこれらのプロセスの制御端末と呼びます。ターミナルを閉じると、対応するプロセスが自動的に閉じられます。

デーモン プロセスはこの制限を突破することができ、実行された瞬間から実行を開始し、システム全体がシャットダウンされるまで終了しません。
プロセスがユーザーや端末、その他の変更の影響を受けないようにする場合は、このプロセスをデーモン プロセスに変える必要があります。 

2. デーモンプロセス作成の原理 (図ではっきりと確認できます)

 

 3. デーモンプロセスの実装(コードブロック)

void init_deamon(void)
{
    /*************** start ****************************/
    pid_t pid;
    int i,max_fd;

    //1,创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(pid > 0)
        exit(0);

    //2,创建新会话
    if(setsid() < 0){
        perror("setsid");
        exit(1);
    }
    //3,再创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(pid > 0)
        exit(0);

    //4,修改守护进程的工作目录
    chdir("/");

    //5,关闭进程父进程的所有的文件描述符
    max_fd = sysconf(_SC_OPEN_MAX);
    for (i = 0; i < max_fd;i++)
        close(i);
    //6,将标准输入,标准输出和标准错误重定向到/dev/null
    open("/dev/null",O_RDWR);
    dup(0);
    dup(0);

    //7,消除umask影响
    umask(0);
    /*************** end ****************************/
}

2.dupとdup2

1. ファイル記述子のコピー

int dup(int oldfd);
//パラメータ----コピーされるファイル記述子
//戻り値----成功: 新しいファイル記述子、失敗:-1

例: 
int main(void)
{     char str[] = "hello world";     int fd1,fd2;


    fd1 = open("1.txt",O_RDWR|O_CREAT,0666);
    if(fd1 < 0){         perror("open");         終了(1);     }


    write(fd1,str,strlen(str));

    fd2 = dup(fd1); //ファイルの説明をコピー fd1
    strcpy(str,"farsight");
    write(fd2,str,strlen(str));

    閉じる(fd1);


    0を返します。
}      
 

2. ファイル記述子のリダイレクト

int dup2(int oldfd, int newfd);
//パラメータ 1 --- 対象のファイル記述子
//パラメータ 2 --- リダイレクト先のファイル記述子
//戻り値 ---- 成功 0、失敗: -1

例: 
int main(void)
{     char str[] = "hello world";     int fd1,fd2;


    fd1 = open("1.txt",O_RDWR|O_CREAT,0666);
    if(fd1 < 0){         perror("open");         終了(1);     fd2     = open("2.txt",O_RDWR|O_CREAT,0666);     if(fd1 < 0){         perror("open");         終了(1);     }







    write(fd1,str,strlen(str));

    dup2(fd1,fd2); // fd2 を fd1 にリダイレクトします

    strcpy(str,"遠視");
    write(fd2,str,strlen(str));
    閉じる(fd1);


    0を返します。
}

3. システムログ

1. ログを開く

#include <syslog.h>
void openlog(const char *ident, int option, intafacility);
//パラメータ 1 ------ //ログ ラベル、カスタマイズされ、見つけやすいログ情報
//パラメータ 2 -- ---- オプション:
                LOG_CONS メッセージをログに送信できない場合は、コンソールに送信します。
                LOG_NDELAY 遅滞なくソケットを開いてメッセージを送信します。
                LOG_NOWAIT 子プロセスを作成し、ブロックせずにメッセージをログに送信します。
                LOG_PERROR ログを送信します。ファイル
                LOG_PID メッセージにプロセス ID を追加
//パラメータ 3 ------ プロセスの種類:
                    LOG_DAEMON デーモン プロセス
                    LOG_FTP tfp サービス プロセス
                    LOG_KERN カーネル プロセス
                    LOG_LPR 印刷サービス プロセス
                    LOG_MAIL メール サービス プロセス

例は次のとおりです。
    openlog("mydaemon",LOG_PID,LOG_DAEMON);

2. メッセージをログに書き込みます

void syslog(int priority, const char *format, ...);
//パラメータ 1 ----- メッセージの優先度
               LOG_EMERG 非常に緊急のエラー
               LOG_ALERT すぐに対処する必要があるエラー
               LOG_CRIT 重大なエラー
               LOG_ERR 一般エラー
               LOG_WARNING 警告
               LOG_NOTICE メッセージ注意が必要です
               LOG_INFO 通常のメッセージ
               LOG_DEBUG デバッグ メッセージ
//パラメータ 2 -----ログにメッセージを書き込む形式
//可変パラメータ----- printf に似た可変パラメータ
例: 
    syslog(LOG_ERR,"fopen: % s",strerror(errno));
    
テストを実行します:
     grep mydaemon /var/log/syslog -n
    203:Sep 26 23:36:26 ubuntu mydaemon[28968]: fopen:No such file or directory

3. ログを閉じます

 void closelog(void);

4. ファイルロック

1.コンセプト

プロセス間の相互排他問題を解決するために、勧告ロックが導入されます。

ファイルを作成する代わりにファイルをロックする方法を使用するには、
    「紳士協定」
    の共有ロックと排他ロックに従って
    、ファイル全体をロックするか、ファイルの特定の部分をロックする (レコード ロック)必要があります。

2. ファイル全体をロックする

#include <sys/file.h>
int flock(int fd, int Operation);
//パラメータ 1 ---- ファイル記述子
//パラメータ 2 ---- ロックの種類: LOCK_SH LOCK_EX LOCK_UN
//戻り値 - --成功: 0、失敗: -1

コード例は次のとおりです。 

コード 1:

int main(int argc,char **argv)
{
    int fd;
    int i;

    if(argc != 2){
        fprintf(stderr,"Usage: %s <filename>\n",argv[0]);
        exit(0);
    }

    if((fd = open(argv[1],O_RDWR)) < 0){
        perror("open");
        exit(1);
    }

    while(1){
        printf("等待获取锁\n");
        //获取互斥锁
        if(flock(fd,LOCK_EX) < 0){
            perror("flock");
            exit(1);
        }

        for(i = 0; i < 7; i++){
            printf("正在上厕所\n");
            sleep(1);
        }
        //释放锁
        if(flock(fd,LOCK_UN) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所出来了....\n");
        sleep(1);
    }
    return 0;
}
 

コード 2:

int main(int argc,char **argv)
{
    int fd;
    int i;

    if(argc != 2){
        fprintf(stderr,"Usage: %s <filename>\n",argv[0]);
        exit(0);
    }

    if((fd = open(argv[1],O_RDWR)) < 0){
        perror("open");
        exit(1);
    }

    while(1){
        printf("等待着上厕所\n");
        //获取互斥锁
        if(flock(fd,LOCK_EX) < 0){
            perror("flock");
            exit(1);
        }
        for(i = 0; i < 7; i++){
            printf("正在上厕所...\n");
            sleep(1);
        }
        //释放锁
        if(flock(fd,LOCK_UN) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所!\n");
        sleep(1);
    }
    return 0;
}

3. ファイルの特定の領域をロックします

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

 struct flock {        short l_type; /* ロックのタイプ: F_RDLCK、F_WRLCK、F_UNLCK */        short l_whence; /* l_start の解釈方法:                            SEEK_SET、SEEK_CUR、SEEK_END */        off_t l_start; /* ロックの開始オフセット */        off_t l_len; /* ロックするバイト数 */        pid_t l_pid; /* ロックをブロックしているプロセスの PID                            (F_GETLK および F_OFD_GETLK によって設定) */    };







 コード例は次のとおりです。

//定义锁的结构体--设置锁的区域
     struct flock fl = {
         .l_whence = SEEK_SET,
        .l_start = 100,
        .l_len  = 1024,
    };

    while(1){
        printf("等待获取锁\n");
        //获取互斥锁
        fl.l_type = F_WRLCK;   //设置锁的类型
        if(fcntl(fd,F_SETLKW,&fl) < 0){
            perror("flock");
            exit(1);
        }

        for(i = 0; i < 7; i++){
            printf("正在上厕所\n");
            sleep(1);
        }
        //释放锁
        fl.l_type = F_UNLCK;    //解锁
        if(fcntl(fd,F_SETLK,&fl) < 0){
            perror("flock");
            exit(1);
        }
        printf("上完厕所出来了....\n");
        sleep(1);
    }

5. プロセス間通信

1. 分類

 Linux のプロセス間通信は、次の 3 つのカテゴリに分類されます。
(1) 初期のプロセス間通信
    未知の名前付きパイプ
    (名前付き) パイプ
    信号
(2) システム V IPC
    メッセージ キュー
    共有メモリ
    セマフォ (ボリューム)
(3) UNIX ドメイン ソケット

2. 名前のないパイプ

2.1 匿名パイプ通信の原理

2.2 使用法

#include <unistd.h>
int Pipe(int Pipefd[2]);
//パラメータ----パイプの両端のファイル記述子を保存する配列
//戻り値---成功: 0、失敗: - 1

 コード例は次のとおりです。
int main(void)
{
    int fd[2];
    pid_t pid;
    char buf[100];

    //创建无名管道
    if(pipe(fd) < 0){   //pipe()会在内核中创建无名管道,然后将管道两端的文件描述符返回给当前进程
        perror("pipe");
        exit(1);
    }

    //创建子进程
    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(!pid){  //子进程执行:从键盘获取字符串,写到管道中
        close(fd[0]);  //关闭读端
        while(1){
            fgets(buf,sizeof(buf),stdin);
            write(fd[1],buf,strlen(buf));   //向管道中写数据
        }
    }else{  //父进程执行:从管道读数据,打印到屏幕上
        close(fd[1]); //关闭写端
        while(1){
           if(read(fd[0],buf,sizeof(buf)) < 0){
                perror("read");
                exit(1);
           }
           printf("%s",buf);
        }
    }

    return 0;
}


要約する

        この記事では、そのプロセスを詳細に説明および補足します。皆様のお役に立てれば幸いです。

        今後は、組み込みや C 言語に関する重要な基礎知識をさらに紹介していきます。Lazy King をサポートしていただき、ありがとうございます。

       このブログが私のすべての友達に役立つことを願っています。最後に、Lazy King に招待された友達があなたの貴重なコメントと注目を残していきます。ありがとう!

おすすめ

転載: blog.csdn.net/weixin_58070962/article/details/133465184