Skip to content

Latest commit

ย 

History

History
1750 lines (1433 loc) ยท 47 KB

File metadata and controls

1750 lines (1433 loc) ยท 47 KB

QUIZ

QUIZ 20181010

  • ์ฒซ ํ€ด์ฆˆ ์ œ์ถœ ๊ฒฐ๊ณผ

    ./QUIZ10-10 submitted.c, 13011022.c
    

QUIZ 20181015

  • ์ˆ˜์—…์‹œ๊ฐ„์— ํŒ€์›๋“ค์ด๋ž‘ ์ œ์ถœํ•œ ๊ฒฐ๊ณผ

    ./QUIZ10-15 submitted.c, 4.c
  • ๋‚ด ์ฝ”๋“œ์— ์ ์šฉํ•œ ๊ฒฐ๊ณผ

    //./QUIZ10-15/13011022.c => ๊ต์ˆ˜๋‹˜ ํ”ผ๋“œ๋ฐฑ ๋ฐ›์€ ๊ฒฐ๊ณผ๋กœ ์ˆ˜์ • ํ–ˆ์Œ
    //์›๋ž˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ ์„ค๊ณ„ํ–ˆ์—ˆ์Œ
    
    ...
    
    int main(int argc, char **argv){
        char in[50], *res[20] = {0};
        char *inst[6] = {"cat", "cd", "cp", "mkdir", "ls", "vi"};
        void (*f[7])(char **) = {cat_m, cd_m, cp_m, mkdir_m, ls_m, vi_m, exec_m};
        int i;
        pid_t pid;
    
        while(1){
            printf("> ");
            gets(in);
            i = 0;
            res[i] = strtok(in, " ");
            if(strcmp(res[0], "exit")==0)
                exit(0);
    
            while(res[i]){
                i++;
                res[i] = strtok(NULL, " ");
            }
    
            for(i=0;i<6;i++){
                if(!strcmp(res[0], inst[i]))
                    break;
            }
    
            if(i == 1){
                cd_m(res);
            }
            else{
                pid = fork();
                if(pid == 0){
                    f[i](res);
                    if(i != 6){
                        exit(0);
                    }
                }
                else{
                    wait(0);
                }
            }
        }
    }
    • cd๋Š” child process๋กœ ์ƒ์„ฑํ•˜๊ณ  parent๋กœ ๋Œ์•„์˜ค๋ฉด ์œ„์น˜๊ฐ€ ์›์ƒ๋ณต๊ท€ ๋˜๋‹ˆ๊นŒ fork()ํ•˜์ง€ ์•Š๋Š”๋‹ค
    • cd ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ๋ช…๋ น๋“ค์€ child process๋กœ ์‹คํ–‰ํ•œ๋‹ค.
    • i == 6 ์ผ ๋•Œ์—๋Š” exit(0)์„ ์‹คํ–‰ ์•ˆ ํ•˜๊ฒŒ ์„ค๊ณ„
      • exec ํ•จ์ˆ˜๊ตฐ์€ ์ธ์ž๋กœ ๋ฐ›์€ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์„ ์ž์‹ ์„ ํ˜ธ์ถœํ•œ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฎ์–ด์“ด๋‹ค ๋”ฐ๋ผ์„œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ˆ˜ํ–‰ ์ค‘์ด๋˜ ๊ธฐ์กด ํ”„๋กœ๊ทธ๋žจ์€ ์ค‘์ง€๋˜์–ด ์—†์–ด์ง€๊ณ  ์ƒˆ๋กœ ๋ฎ์–ด์“ด ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋œ๋‹ค exec ํ•จ์ˆ˜๊ตฐ์„ ํ˜ธ์ถœํ•œ ํ”„๋กœ์„ธ์Šค ์ž์ฒด๊ฐ€ ๋ฐ”๋€Œ๋ฏ€๋กœ, exec ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ์„ฑ๊ณตํ•˜๋ฉด ๋ฆฌํ„ด๊ฐ’์ด ์—†๋‹ค Exec ํ•จ์ˆ˜๊ตฐ์€ forkํ•จ์ˆ˜์™€ ์—ฐ๊ฒฐํ•ด fork๋กœ ์ƒ์„ฑํ•œ ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋„๋ก ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค
      • fork ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ƒ์„ฑํ•œ ์ž์‹ ํ”„๋กœ์„ธ์„œ์™€ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ๋‹ค case๋กœ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์™€ ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ˆ˜ํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ์‹คํ–‰ํ•œ๊ฑฐ์ง€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•œ๋‹ค
      • ๊ทธ๋Ÿฌ๋‚˜ ์ž์‹ ํ”„๋กœ์„ธ์Šค์—์„œ execํ•จ์ˆ˜๊ตฐ์„ ํ˜ธ์ถœํ•˜๋ฉด ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋กœ๋ถ€ํ„ฐ ๋ณต์‚ฌํ•œ ํ”„๋กœ๊ทธ๋žจ๊ณผ๋Š” ๋‹ค๋ฅธ ๋ช…๋ น์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค ์‰˜์€ forkํ•จ์ˆ˜๋กœ ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ช…๋ น์ด๋‚˜ ํŒŒ์ผ์„ execํ•จ์ˆ˜๊ตฐ์„ ์‚ฌ์šฉํ•ด ์ž์‹ ํ”„๋กœ์„ธ์Šค์—์„œ ์‹คํ–‰ํ•œ๋‹ค ์ด๋ ‡๊ฒŒ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์™€ ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ๋•Œ fork์™€ execํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค
      • execํ•จ์ˆ˜๊ตฐ๋“ค์€ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ๋•Œ ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฎ์–ด ์จ๋ฒ„๋ฆฐ๋‹ค ๊ทธ๋ž˜์„œ exec ํ•จ์ˆ˜๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด ํ•จ์ˆ˜ ์ดํ›„์— ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋“ค์€ ์‹คํ–‰์ด ์•ˆ ๋œ๋‹ค ๊ทธ๋Ÿฌ๋‚˜ exec ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰์— ์‹คํŒจํ•˜๋ฉด ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋”ฉ์ด ์•ˆ ๋˜์–ด exec ํ•จ์ˆ˜ ๋‹ค์Œ ์ฝ”๋“œ๋“ค์ด ์‹คํ–‰๋œ๋‹ค execํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์›๋ž˜์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‚ฌ๋ผ์ ธ ๋ฒ„๋ฆฌ๋Š” ๊ฑธ ์›์น˜ ์•Š์œผ๋‹ˆ fork๋ฅผ ํ•œ ํ›„์— execํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค
  • ๊ต์ˆ˜๋‹˜ ํ”ผ๋“œ๋ฐฑ ์ดํ›„ exec ํ•จ์ˆ˜๊ตฐ์ด ์ œ๋Œ€๋กœ ์‹คํ–‰๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ, ๋ชจ๋“  ๊ฒฝ์šฐ์— exit(0)์„ ํ•ด์ฃผ๋Š”๊ฒŒ ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํ•จ

    ./QUIZ10-15 submitted.c, 4.c, 13011022.c

QUIZ 20181017

  • backupํ•จ์ˆ˜ ๋„์›€ ๋ฐ›์•„์„œ ์™„์„ฑ ๊ธฐ์กด์— ๋งŒ๋“  cp๋ฅผ ํ™œ์šฉ์„ ๋ชปํ•จ. ๊ทธ๋ž˜์„œ ๋‹ค์‹œ ๋งŒ๋“ฌ

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <string.h>
    #include <time.h>
    #include <ftw.h>
    #include <stdlib.h>
    
    #define BUFSIZE 512
    
    int backup(const char *name, const struct stat *status, int type){
    
        char buffer[BUFSIZE], file1[BUFSIZE], file2[BUFSIZE] = "./TEMP/";
        int fd1, fd2, i, nread;
    
        if(type == FTW_F){
    
            if(strncmp((char*)name, "./TEMP", 6) == 0)
                return 0;
    
            fd1 = open(name, O_RDONLY);
    
            strcpy(file1, name + 2);
    
            for(i=0;i<strlen(file1);i++){
                if(file1[i] == '/')
                    file1[i] = '_';
            }
    
            strcat(file2, file1);
    
            fd2 = open(file2, O_WRONLY | O_CREAT, status->st_mode&0777);
    
            nread = read(fd1, buffer, BUFSIZE);
            while(nread > 0){
                write(fd2, buffer, nread);
                nread = read(fd1, buffer, BUFSIZE);
            }
        }
    
        return 0;
    }
    • ์‹œํ—˜๋ฒ”์œ„ 2-6์žฅ, ์„ค๊ณ„๊ณผ์ œ 1, 2-1, 2-2 backup ์ฝ”๋”ฉ๊นŒ์ง€ ์›”์š”์ผ ํ•„๊ธฐ, ์ˆ˜์š”์ผ ์‹ค๊ธฐ

2-2 ์™„์„ฑ ์ฝ”๋“œ(ํŒ€)

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <ftw.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

void cat_m(char ** data){ /* 16010977 */

   char * filename = data[1];
   char buff[512];
   int fd = open(filename, O_RDONLY);
   int size;

   while(size = read(fd, buff, sizeof(buff))){

      write(0, buff, size);

   }
   close(fd);
}

void cd_m(char ** data){ /* 16010977 */
   chdir(data[1]); 
}
void cp_m(char ** data){
   char * file_in = data[1];
   char * file_out = data[2];
   char buff[512];
   int in, out;
   int size;

   in = open(file_in, O_RDONLY);
   out = open(file_out, O_CREAT | O_WRONLY, 0644);

   while(size = read(in, buff, sizeof(buff))){
      write(out, buff, size);
   }
   close(in);
   close(out);

}
void mkdir_m(char ** data){ /* 16010977 */
   int mode = 0755;
   mkdir(data[1], mode);
}
void ls_m(char ** data){ /* 16010977 */
   DIR * dir;
   struct dirent *ent;

   dir = opendir(".");

   while(ent = readdir(dir)){
      printf("%s\n", ent->d_name);
   }

   closedir(dir);
}

void vi_m(char ** data){ /* 16010977  */
   int fd;
   char buff[512];
   int size;
   int flag = 0;


   fd = open(data[1], O_WRONLY | O_APPEND);

   if (fd != -1){
      cat_m(data);

   }
   else{
      fd = open(data[1], O_CREAT | O_WRONLY, 0644);
   }

   while(size = read(0, buff, sizeof(buff))){
      if (strncmp(buff+size-5, "quit", 4) == 0){
         size -= 5;
         flag = 1;
      }
      write(fd, buff, size);
      if (flag == 1) break;
   }

   close(fd);


}   


int backup_file(const char * name, const struct stat * st, int type){

   char buff[512];
   char output[512] ="./TEMP/";
   int in, out;
   int i, size;

   if (type != FTW_F){
      return 0;
   }      

   if (strncmp(output, name, 7) == 0) return 0;

   strcpy(buff, name);
   strcat(output, name+2);

   for(i = 7; output[i]; i++){
      if (output[i] == '/')
         output[i] = '_';
   }

   in = open(buff, O_RDONLY);
   out = open(output, O_CREAT | O_WRONLY | O_TRUNC, st->st_mode);

   while(size = read(in, buff, sizeof(buff))){
      write(out, buff, size);
   }

   close(in);
   close(out);

   return 0;
}

void backup(){
   mkdir("TEMP", 0777);
   ftw(".", backup_file, 1);
}

void exec_m(char **s){   /* 16011025 */
   execv(s[0],s);
}


int main(void){
   char in[50], *res[20] = {0};
   char *inst[7]={"cat","cd","cp", "mkdir","ls","vi", "backup"};
   void (*f[8])(char **)={cat_m, cd_m, cp_m, mkdir_m, ls_m, vi_m, backup, exec_m };
   int i;
   pid_t pid, b_pid;
   int background = 0;

   while(1){
      printf("> ");
      gets(in);
      i = 0;
      res[i] = strtok(in, " ");
      if (strcmp(res[0], "exit") ==0)
         exit(0);

      while(res[i]){
         i++;
         res[i] = strtok(NULL, " ");
      }

      for(i = 0; i < 7; i++){
         if (!strcmp(res[0], inst[i]))
            break;
      }
      if (i == 1){
         cd_m(res);
      }
      else{
         if (i == 6){
            background++;
            b_pid = fork();
            if (b_pid == 0){
               backup();
               exit(0);

            }
         }
         else{
            pid = fork();
            if (pid == 0){
               f[i](res);   
               exit(0); 
            }
            else{
               waitpid(pid, 0, 0);
            }
         }
      }
      if (background){
         if(waitpid(b_pid, 0, WNOHANG)){
            background = 0;
         }
      }
   }
}

2-2 ๋‚ด ์ฝ”๋“œ ๋‹ค๋“ฌ๊ณ , ์ค‘๊ฐ„๊ณ ์‚ฌ backup ๋ฐ rmall ์ถ”๊ฐ€

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
#include <ftw.h>
#include <stdlib.h>

#define BUFSIZE 512

void cat_m(char **s){
    char buffer[BUFSIZE];
    int nread, fd = open(s[1], O_RDONLY);

    while((nread = read(fd, buffer, BUFSIZE)) > 0){
        write(1, buffer, nread);
    }

    close(fd);
}

void cd_m(char **s){
    chdir(s[1]);
}

void cp_m(char **s){
    char buffer[BUFSIZE];
    int fd1, fd2, nread;

    fd1 = open(s[1], O_RDONLY);

    if (fd1 == -1) {
        return;
    } else {
        fd2 = open(s[2], O_WRONLY | O_CREAT | O_EXCL, 0777);

        if(fd2 == -1){
            fd2 = open(s[2], O_WRONLY | O_CREAT | O_TRUNC, 0777);
        }

        while((nread = read(fd1, buffer, BUFSIZE)) > 0){
            write(fd2, buffer, nread);
        }
    }

    close(fd1);
    close(fd2);
}

void mkdir_m(char **s){
    mkdir(s[1], 0777);
}

void ls_m(char **s){
    DIR *dp;
    struct dirent *d;
    dp = opendir(".");
    while((d = readdir(dp)) != NULL){
        if(d->d_name[0] != '.'){
            printf("%s\n", d->d_name);
        }
    }
}

void vi_m(char **s){
    char buffer[BUFSIZE];
    int nread, fd = open(s[1], O_RDWR|O_CREAT, 0777);

    //์žˆ์œผ๋ฉด ํŒŒ์ผ ์•ˆ ๋งŒ๋“ค๊ณ , ์—†์œผ๋ฉด ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ, ํŒŒ์ผ์— ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ ํ˜€์žˆ๋“  ์ ํ˜€์žˆ๋“  ๋‹ค ์ถœ๋ ฅ์„ ํ•ด์ฃผ๊ณ ,
    //๊ทธ๋Ÿฌ๋ฉด ํŒŒ์ผ ํฌ์ธํ„ฐ๊ฐ€ ์ œ์ผ ๋’ค๋กœ ๊ฐ€์žˆ์–ด์„œ ๋ฐ”๋กœ ๊ทธ ๋’ค์— ์ด์–ด์ ์„ ๋‚ด์šฉ๋“ค์„ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ค.ใ„ด

    while((nread = read(fd, buffer, BUFSIZE)) > 0){
        write(1, buffer, nread);
    }
    while((nread = read(0, buffer, BUFSIZE)) > 0){
        //์ด๋ ‡๊ฒŒ ๋งˆ์ง€๋ง‰ new line ๋ฌธ์ž๋„ ์ฒดํฌ๋ฅผ ํ•ด์ฃผ๋ฉด ๋” ํ™•์‹คํ•œ ์ข…๋ฃŒ ์ฝ”๋“œ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Œ
        if((strncmp(buffer, "quit", 4) == 0) && (buffer[4] == '\n'))
            break;
        write(fd, buffer, nread);
    }
}

////์ง€์ • TEMP ํด๋”์—๋งŒ ๋ฐฑ์—… ์‹คํ–‰
//int backup(const char *name, const struct stat *status, int type){
//    char buffer[BUFSIZE], file1[BUFSIZE], file2[BUFSIZE] = "./TEMP/";
//    int fd1, fd2, i, nread;
//
//    if(type == FTW_F){
//        if(strncmp((char*)name, "./TEMP", 6) == 0)
//            return 0;
//
//        fd1 = open(name, O_RDONLY);
//
//        strcpy(file1, name + 2);
//
//        for(i=0;i<strlen(file1);i++){
//            if(file1[i] == '/')
//                file1[i] = '_';
//        }
//
//        strcat(file2, file1);
//
//        fd2 = open(file2, O_WRONLY | O_CREAT, status->st_mode&0777);
//
//        while((nread = read(fd1, buffer, BUFSIZE)) > 0){
//            write(fd2, buffer, nread);
//        }
//    }
//    return 0;
//}

char b_dir[BUFSIZE] = "./";

//์ธ์ž๋กœ ๋„˜๊ฒจ์ค€ ํด๋” ์ƒ์„ฑ ํ›„ ๋ฐฑ์—… ์‹คํ–‰
int backup(const char *name, const struct stat *status, int type){
    char buffer[BUFSIZE], file1[BUFSIZE], file2[BUFSIZE];
    int fd1, fd2, i, nread;

    strcpy(file2, b_dir);

    if(type == FTW_F){
        if(strncmp((char*)name, file2, strlen(file2)) == 0)
            return 0;

        fd1 = open(name, O_RDONLY);
        strcpy(file1, name + 2);

        for(i=0;i<strlen(file1);i++){
            if(file1[i] == '/')
                file1[i] = '_';
        }

        strcat(file2, file1);
        fd2 = open(file2, O_WRONLY | O_CREAT, status->st_mode&0777);

        while((nread = read(fd1, buffer, BUFSIZE)) > 0){
            write(fd2, buffer, nread);
        }
    }
    return 0;
}

void backup_m(char **s){
    strcat(b_dir, s[1]);
    strcat(b_dir, "/");
    mkdir(b_dir, 0777);
    ftw(".", backup, 1);
}

void exec_m(char **s){
    execv(s[0], s);
}

int flag;

int delete_all(const char *name, const struct stat *status, int type){

    int cnt = 0;
    DIR *dp;
    struct dirent *d;

    if(type == FTW_F){
        remove(name);
    }
    else if(type == FTW_D){
        dp = opendir(name);
        while(d = readdir(dp))
            cnt++;
        if(cnt <= 2)
            rmdir(name);
        else
            flag = 1;
    }
    return 0;
}

void rmall_m(char **s){
    do{
        flag = 0;
        ftw(s[1], delete_all, 1);
    }while(flag == 1);
}

//int delete_file(const char *name, const struct stat *status, int type){
//
//    if(type == FTW_F){
//        unlink(name);
//    }
//
//    return 0;
//}
//
//int delete_directory(const char *name, const struct stat *status, int type){
//
//    int k;
//    struct dirent *d;
//    DIR *dp;
//
//    if(type == FTW_D){
//        rmdir(name);
//    }
//
//    return 0;
//}
//
//void rmall_m(char **s){
//    ftw(s[1], delete_file, 1);
//    ftw(s[1], delete_directory, 1);
//}

int main(int argc, char **argv){
    char in[50], *res[20] = {0};
    char *inst[8] = {"cat", "cd", "cp", "mkdir", "ls", "vi", "backup", "rmall"};
    void (*f[9])(char **) = {cat_m, cd_m, cp_m, mkdir_m, ls_m, vi_m, backup_m, rmall_m, exec_m};
    int i, background = 0;
    pid_t pid, b_pid;

    while(1){
        printf("> ");
        gets(in);
        i = 0;
        res[i] = strtok(in, " ");
        if(strcmp(res[0], "exit")==0)
            exit(0);

        while(res[i]){
            i++;
            res[i] = strtok(NULL, " ");
        }

        for(i=0;i<8;i++){
            if(!strcmp(res[0], inst[i]))
                break;
        }

        if(i == 1){
            cd_m(res);
        }
        else{
            if (i == 6){
                background++;
                b_pid = fork();
                if (b_pid == 0){
                    f[i](res);
                    exit(0);

                }
            }
            else{
                pid = fork();
                if (pid == 0){
                    f[i](res);
                    exit(0);
                }
                else{
                    waitpid(pid, 0, 0);
                }
            }
        }
        if (background){
            if(waitpid(b_pid, 0, WNOHANG)){
                background = 0;
            }
        }
    }
}
  • ์‹œํ—˜ ์ฃผ์˜ ์‚ฌํ•ญ
    • Backup ํ•จ์ˆ˜ ์‹คํ–‰ํ•  ๋•Œ backupํ•œ ํŒŒ์ผ๋“ค๋„ ๊ณ„์†ํ•ด์„œ ๋ณต์‚ฌ/๋ถ™์ด๊ธฐ๋ฅผ ํ•  ํ•„์š”๊ฐ€ ์—†์Œ. ๊ทธ๋ž˜์„œ backup์„ ํ•œ ๋””๋ ‰ํ† ๋ฆฌ ํด๋”๋ฅผ 0333 permission์„ ์ฃผ๋ฉด FTW_DNR ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋˜์–ด์„œ ๋ณต์‚ฌ๋ฅผ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค.
    • rmall ํ•จ์ˆ˜ ์‹คํ–‰ํ•  ๋•Œ ์‹œํ—˜ ์ค‘์ธ ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ ์ง€์šฐ๊ฒŒ ์„ค์ •์„ ํ•ด์ฃผ๋ ค๋ฉด 0555๋กœ ์„ค์ •์„ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

20181128 3-1 ์„ค๊ณ„๊ณผ์ œ

  • ์‹œํ—˜์€ ๋งํ–ˆ์ง€๋งŒ ๋‹ค์‹œ ํ’€์–ด๋ดค์Œ.

    • ๊ทผ๋ฐ ๋‹ค์‹œ ํ’€์–ด๋ณธ ์ฝ”๋“œ์—์„œ๋Š” ctrl + c ์‹œ๊ทธ๋„์„ ๋ฌด์‹œ๋ฅผ ํ•˜๊ธดํ•˜๋Š”๋ฐ child ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜์ง€ ์•Š์•„์„œ ์ž˜๋ชป๋œ ์ฝ”๋“œ์˜€์Œ
    • ๋ฐฑ์—… ๊ธฐ๋Šฅ ์‹คํ–‰ํ•  ๋•Œ exitํ•˜๊ฒŒ ๋˜๋ฉด ์‹œ๊ทธ๋„ ๋ณด๋‚ด์„œ ์ž‘์—… ๋„์ค‘์—๋Š” ์‹œ๊ทธ๋„ ์ž ์‹œ ๋ฌด์‹œํ–ˆ๋‹ค๊ฐ€ ์ž‘์—… ๋๋‚˜๋ฉด ๋ธ”๋ก ํ’€์–ด์ค˜์„œ ์‹œ๊ทธ๋„ ์•ก์…˜ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ ๊ฑฐ๋Š” ๋งž๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์–ด์ฐจํ”ผ ์ œ์ถœ ์ฝ”๋“œ์—๋Š” ์•ˆ ๋ผ์žˆ์–ด์„œ ์ ์ˆ˜๋Š” ์—†๋‹ค.
  • 20181212 ์ˆ˜์—… ๋•Œ ๊ต์ˆ˜๋‹˜์ด ๋‹ค์‹œ ๋งŒ๋“ค์–ด์˜ค๋ฉด ์ ์ˆ˜๋ฅผ ์ค€๋‹ค๊ณ  ํ•ด์„œ ๋‹ค์‹œ ํ•ด๋ดค์Œ

  • ์ˆ˜์ •์‚ฌํ•ญ

    • ๊ธฐ๋ณธ์ ์œผ๋กœ parent์—์„œ๋Š” ctrl + c ์‹œ๊ทธ๋„์„ ๋ฌด์‹œํ•˜๊ฒŒ ์„ค์ •ํ•ด๋‘๋ฉด, shell process๊ฐ€ ์‹คํ–‰ํ•˜๋Š” cd ๋ฐ ์ค‘๊ฐ„์— ์ข…๋ฃŒ๋˜๋ฉด ์•ˆ ๋˜๋Š” backup ๋ช…๋ น ์ž‘์—…์€ ctrl + c ์‹œ๊ทธ๋„์„ ๋ฌด์‹œํ•จ
    • child ํ”„๋กœ์„ธ์Šค๋กœ ์‹คํ–‰๋˜๋Š” ๋‚˜๋จธ์ง€ ๋ช…๋ น๋“ค์€ ctrl + c default signal action์„ ์ทจํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ฃผ๊ณ  ํ•จ์ˆ˜ ์‹คํ–‰.
    • Child ํ”„๋กœ์„ธ์Šค๋งŒ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ตฌ๊ฐ„์—์„œ ์„ค์ •์„ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— parent signal ์„ค์ •์—๋Š” ์˜ํ–ฅ์ด ์—†๋‹ค
#define BUFSIZE 512

void catchusr(int);
void catchusr2(int);
void catchalarm(int);

void cat_m(char **s){
    char buffer[BUFSIZE];
    int nread, fd = open(s[1], O_RDONLY);

    while((nread = read(fd, buffer, BUFSIZE)) > 0){
        write(1, buffer, nread);
    }

    close(fd);
}

void cd_m(char **s){
    chdir(s[1]);
}

void cp_m(char **s){
    char buffer[BUFSIZE];
    int fd1, fd2, nread;

    fd1 = open(s[1], O_RDONLY);

    if (fd1 == -1) {
        return;
    } else {
        fd2 = open(s[2], O_WRONLY | O_CREAT | O_EXCL, 0777);

        if(fd2 == -1){
            fd2 = open(s[2], O_WRONLY | O_CREAT | O_TRUNC, 0777);
        }

        while((nread = read(fd1, buffer, BUFSIZE)) > 0){
            write(fd2, buffer, nread);
        }
    }

    close(fd1);
    close(fd2);
}

void mkdir_m(char **s){
    mkdir(s[1], 0777);
}

void ls_m(char **s){
    DIR *dp;
    struct dirent *d;
    dp = opendir(".");
    while((d = readdir(dp)) != NULL){
        if(d->d_name[0] != '.'){
            printf("%s\n", d->d_name);
        }
    }
}

void vi_m(char **s){
    char buffer[BUFSIZE];
    int nread, fd = open(s[1], O_RDWR|O_CREAT, 0777);

    while((nread = read(fd, buffer, BUFSIZE)) > 0){
        write(1, buffer, nread);
    }
    while((nread = read(0, buffer, BUFSIZE)) > 0){
        if((strncmp(buffer, "quit", 4) == 0) && (buffer[4] == '\n'))
            break;
        write(fd, buffer, nread);
    }
}

int backup(const char *name, const struct stat *status, int type){
    char buffer[BUFSIZE], file1[BUFSIZE], file2[BUFSIZE] = "./TEMP/";
    int fd1, fd2, i, nread;

    if(type == FTW_F){
        fd1 = open(name, O_RDONLY);
        strcpy(file1, name + 2);

        for(i=0;i<strlen(file1);i++){
            if(file1[i] == '/')
                file1[i] = '_';
        }

        strcat(file2, file1);
        fd2 = open(file2, O_WRONLY | O_CREAT, status->st_mode&0777);

        while((nread = read(fd1, buffer, BUFSIZE)) > 0){
            write(fd2, buffer, nread);
        }
    }
    return 0;
}

void backup_m(char **s){
    sigset_t mask;

    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR2);

    while(1){
        //backup ๋„์ค‘์—๋Š” user signal2 ๋Š” block ๋๋‹ค๊ฐ€, unblock ํ›„์— signal handle action์„ ์‹คํ–‰ํ•˜๊ฒŒ sigprocmask ์‚ฌ์šฉ
        sigprocmask(SIG_SETMASK, &mask, NULL);
        printf("*****BACK-UP STARTS*****\n");
        mkdir("TEMP", 0333);
        sleep(5);
        ftw(".", backup, 1);
        printf("*****BACK-UP ENDS*****\n");
        sigprocmask(SIG_UNBLOCK, &mask, NULL);

        alarm(10);
        //pause๋ฅผ ์•ˆ ํ•ด์ฃผ๋ฉด 10์ดˆ๋ฅผ ์•ˆ ์‰ฌ๊ณ  ์•Œ๋žŒ ๋ณด๋‚ด๊ณ  ๋ฐ”๋กœ ๋‹ค์‹œ backup์ž‘์—…์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— pause๋กœ ๋ธ”๋ฝ์‹œํ‚ค๊ณ , alarm signal handleํ• ๋•Œ pause๋ฅผ ํ’€์–ด์ฃผ๋ฉด ๋œ๋‹ค.
        pause();
    }
}

void exec_m(char **s){
    execv(s[0], s);
}

//pause๋ฅผ ํ’€์–ด์ฃผ๊ธฐ ์œ„ํ•œ signal action
void catchusr(int signo){
    return ;
}

//parent์—์„œ exit์„ ์ž…๋ ฅ๋ฐ›์œผ๋ฉด backup child ํ”„๋กœ์„ธ์Šค๋กœ ์‹ ํ˜ธ๋ฅผ ๋ณด๋ƒ„
void catchusr2(int signo){
    exit(1);
}

//10์ดˆ ์•Œ๋žŒ ํ›„์— pause๋ฅผ ํ’€์–ด์ฃผ๊ธฐ ์œ„ํ•œ signal ๋ณด๋‚ด๋Š” ๊ฒƒ
void catchalarm(int signo){
    kill(getpid(), SIGUSR1);
}

int main(int argc, char **argv){
    char in[50], *res[20] = {0};
    char *inst[7] = {"cat", "cd", "cp", "mkdir", "ls", "vi", "backup"};
    void (*f[8])(char **) = {cat_m, cd_m, cp_m, mkdir_m, ls_m, vi_m, backup_m, exec_m};
    int i, status;
    pid_t pid, b_pid;

    static struct sigaction act;

    //๊ธฐ๋ณธ์ ์œผ๋กœ parent์—์„œ๋Š” ctrl + c ์‹œ๊ทธ๋„์„ ๋ฌด์‹œํ•˜๊ฒŒ ์„ค์ •ํ•ด๋‘๋ฉด, shell process๊ฐ€ ์‹คํ–‰ํ•˜๋Š” cd ๋ฐ ์ค‘๊ฐ„์— ์ข…๋ฃŒ๋˜๋ฉด ์•ˆ ๋˜๋Š” backup ๋ช…๋ น ์ž‘์—…์€ ctrl + c ์‹œ๊ทธ๋„์„ ๋ฌด์‹œํ•จ
    act.sa_handler = SIG_IGN;
    sigaction(SIGINT, &act, NULL);

    act.sa_handler = catchalarm;
    sigaction(SIGALRM, &act, NULL);

    act.sa_handler = catchusr;
    sigaction(SIGUSR1, &act, NULL);

    act.sa_handler = catchusr2;
    sigaction(SIGUSR2, &act, NULL);

    while(1){
        printf("> ");
        gets(in);
        i = 0;
        res[i] = strtok(in, " ");
        if(strcmp(res[0], "exit")==0){
            kill(b_pid, SIGUSR2);
            while(waitpid(b_pid, 0, WNOHANG) == 0){
                printf(".....wait for backup .....\n");
                sleep(1);
            }
            exit(0);
        }

        while(res[i]){
            i++;
            res[i] = strtok(NULL, " ");
        }

        for(i=0;i<7;i++){
            if(!strcmp(res[0], inst[i]))
                break;
        }

        if(i == 1){
            cd_m(res);
        }
        else{
            if (i == 6){
                b_pid = fork();
                if (b_pid == 0){
                    f[i](res);
                    exit(0);
                }
                else{
                    waitpid(b_pid, 0, WNOHANG);
                }
            }
            else{
                pid = fork();
                if (pid == 0){
                    //child ํ”„๋กœ์„ธ์Šค๋กœ ์‹คํ–‰๋˜๋Š” ๋‚˜๋จธ์ง€ ๋ช…๋ น๋“ค์€ ctrl + c default signal action์„ ์ทจํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ฃผ๊ณ  ํ•จ์ˆ˜ ์‹คํ–‰
                    act.sa_handler = SIG_DFL;
                    sigaction(SIGINT, &act, NULL);

                    f[i](res);
                    exit(0);
                }
                else{
                    waitpid(pid, &status, 0);
                }
            }
        }

        //์‹œ๊ทธ๋„์„ ๋ฐ›๊ณ  ์ข…๋ฃŒํ•œ pid์ธ ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰์— newline์ด ์ถœ๋ ฅ ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ถœ๋ ฅ ์ด์˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ถ”๊ฐ€ํ•ด์คŒ
        if(WIFSIGNALED(status))
            printf("\n");

    }
}

20181203 4-1 ์„ค๊ณ„๊ณผ์ œ

๊ต์ˆ˜๋‹˜์ด ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋งŒ๋“ ๊ฑฐ

  • ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋จผ์ € ํ•œ ๋ฒˆ ์ฝ”๋”ฉํ•ด๋ดค์Œ

    • ์ผ๋‹จ ๋ฉ”์„ธ์ง€ ํ๋งŒ ์ด์šฉํ•˜์—ฌ ์ฑ„ํŒ…์— ์ฐธ์—ฌํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์•ˆ ์„ž์ด๊ณ  ์ž˜ ์ „๋‹ฌํ•˜๊ฒŒ๋Š” ๋งŒ๋“ค์—ˆ๋Š”๋ฐ,,,
    • ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฑ„ํŒ… ์ฐธ์—ฌํ•œ ์ธ์›์„ ํŒŒ์•…ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๋” ์†์„ ๋ด์ค˜์•ผํ•จ.
    #define BUFSIZE 512
    
    int total_user, id_counter;
    
    struct q_entry{
        long mtype;
        int id_counter;
        int total_user;
    };
    
    struct q_data{
        long mtype;
        int id;
        char mtext[BUFSIZE];
    };
    
    void receiver(int id, int qid){
        struct q_entry user_count;
        struct q_data user_message;
    
        while(msgrcv(qid, &user_message, sizeof(struct q_data), 3, 0) > 0){
            msgrcv(qid, &user_message, sizeof(struct q_data), 2, 0);
    
            if(user_message.id != id)
                printf("[received] id : %d, message : %s\n", user_message.id, user_message.mtext);
            else{
                if ((strncmp(user_message.mtext, "talk_quit", 9) == 0) && (user_message.mtext[9] == '\n')) {
                    exit(1);
                }
            }
        }
    
        exit(1);
    }
    
    void sender(int id, int qid){
        int i;
        char buffer[BUFSIZE];
        struct q_entry user_count;
        struct q_data user_message;
    
        while((read(0, buffer, BUFSIZE)) > 0) {
            msgrcv(qid, &user_count, 2*sizeof(int), 1, IPC_NOWAIT);
            user_count.mtype = 1;
            id_counter = user_count.id_counter;
            total_user = user_count.total_user;
            msgsnd(qid, &user_count, 2*sizeof(int), 0);
    
            if(total_user == 1){
                printf("talk_wait ... \n");
            }
    
            if ((strncmp(buffer, "talk_quit", 9) == 0) && (buffer[9] == '\n')) {
                for(i=0;i<total_user;i++){
                    user_message.mtype = 3;
                    user_message.id = id;
                    strcpy(user_message.mtext, buffer);
                    msgsnd(qid, &user_message, sizeof(struct q_data), 0);
                }
                for(i=0;i<total_user;i++){
                    user_message.mtype = 2;
                    user_message.id = id;
                    strcpy(user_message.mtext, buffer);
                    msgsnd(qid, &user_message, sizeof(struct q_data), 0);
                }
                return;
            }
    
            for(i=0;i<total_user;i++){
                user_message.mtype = 3;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }
            for(i=0;i<total_user;i++){
                user_message.mtype = 2;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }
    
            strcpy(buffer, "\0");
        }
    
        return;
    }
    
    int main(int argc, char **argv){
        int i, id, qid;
        char buffer[BUFSIZE];
        key_t key;
        pid_t pid;
        struct q_entry user_count;
        struct q_data user_message;
    
        key = ftok("keyfile", 1);
        qid = msgget(key, 0600|IPC_CREAT);
    
        if(msgrcv(qid, &user_count, 2*sizeof(int), 1, IPC_NOWAIT) < 0){
            id_counter = 1;
            total_user = 1;
    
            user_count.mtype = 1;
            user_count.id_counter = id_counter;
            user_count.total_user = total_user;
            id = id_counter;
            msgsnd(qid, &user_count, 2*sizeof(int), 0);
        }
        else{
            id_counter = user_count.id_counter + 1;
            total_user = user_count.total_user + 1;
    
            user_count.mtype = 1;
            user_count.id_counter = id_counter;
            user_count.total_user = total_user;
            id = id_counter;
            msgsnd(qid, &user_count, 2*sizeof(int), 0);
        }
    
        printf("id = %d\n", id);
    
        pid = fork();
        if(pid == 0){
            receiver(id, qid);
        }
        else{
            waitpid(pid, 0, WNOHANG);
            sender(id, qid);
        }
    
        msgrcv(qid, &user_count, 2*sizeof(int), 1, IPC_NOWAIT);
        id_counter = user_count.id_counter;
        total_user = user_count.total_user;
    
        user_count.mtype = 1;
        user_count.id_counter = id_counter;
        user_count.total_user = total_user - 1;
        msgsnd(qid, &user_count, 2*sizeof(int), 0);
    
        if(user_count.total_user == 0){
            printf("no user exists\n");
            msgctl(qid, IPC_RMID, 0);
        }
    
        exit(1);
    }

๊ต์ˆ˜๋‹˜ ํ”ผ๋“œ๋ฐฑ ๋ฐ›๊ณ  ๋‹ค์‹œ ๋งŒ๋“  ๋ฒ„์ „

  • ์„ค๊ณ„ ๋ฐฉ๋ฒ•
    • mtype = 1์ธ ๊ฒฝ์šฐ๋Š” ์ฑ„ํŒ…์ฐธ๊ฐ€ํ•˜๊ณ  ์žˆ๋Š” ์ด์ธ์› ๊ด€๋ฆฌ, id ์นด์šดํ„ฐ, message ์นด์šดํ„ฐ๋ฅผ ๊ด€๋ฆฌ
    • mtype = 2์ธ ๊ฒฝ์šฐ๋Š” ๋ฉ”์„ธ์ง€ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ด€๋ฆฌ
    • mtype = 1์„ ์ œ์™ธํ•œ 2๋ถ€ํ„ฐ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด๋ฉด ์นด์šดํ„ฐ๋ฅผ ํ•˜๋‚˜์”ฉ ์˜ฌ๋ ค์„œ ๋ณด๋‚ธ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด ์ฝ์„ ๋•Œ ๋ฉ”์„ธ์ง€ ์นด์šดํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ์ฝ๊ฒŒ ํ•˜์—ฌ ๋ฉ”์„ธ์ง€๊ฐ€ ์„ž์ด์ง€ ์•Š๊ฒŒ ์„ค์ •ํ•จ
    • ๋ฌธ์ž์—ด ์ œ๋Œ€๋กœ ์ „๋‹ฌ๋˜๊ฒŒ gets(buffer)๋กœ ์ˆ˜์ •
  • ๊ฐœ์„ ํ•ด์•ผํ•  ์‚ฌํ•ญ
    • talk_wait, talk_start ๋ถ€๋ถ„
#define BUFSIZE 512

int id_counter, total_user, message_counter;

struct q_entry{
    long mtype;
    int id_counter;
    int total_user;
    int message_counter;
};

struct q_data{
    long mtype;
    int id;
    char mtext[BUFSIZE];
};

void receiver(int id, int qid){
    struct q_entry user_count;
    struct q_data user_message;

    while(msgrcv(qid, &user_message, sizeof(struct q_data), message_counter, 0) > 0){
        if(user_message.id != id)
            printf("[received] id : %d, message : %s\n", user_message.id, user_message.mtext);
        else{
            if ((strcmp(user_message.mtext, "talk_quit") == 0)) {
                exit(1);
            }
        }
        message_counter++;
    }
    exit(1);
}

void sender(int id, int qid){
    int i;
    char buffer[BUFSIZE];
    struct q_entry user_count;
    struct q_data user_message;

    while(gets(buffer)) {
        msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT);
        user_count.mtype = 1;
        id_counter = user_count.id_counter;
        total_user = user_count.total_user;
        message_counter = user_count.message_counter;

        if(total_user == 1){
            printf("talk_wait ... \n");
        }

        if ((strcmp(buffer, "talk_quit") == 0)) {
            for(i=0;i<total_user;i++){
                user_message.mtype = message_counter;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }

            user_count.mtype = 1;
            message_counter++;
            user_count.message_counter = message_counter;
            msgsnd(qid, &user_count, 3*sizeof(int), 0);

            return;
        }
        else{
            for(i=0;i<total_user;i++){
                user_message.mtype = message_counter;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }

            user_count.mtype = 1;
            message_counter++;
            user_count.message_counter = message_counter;
            msgsnd(qid, &user_count, 3*sizeof(int), 0);
        }
    }
    return;
}

int main(int argc, char **argv){
    int id, qid;
    key_t key;
    pid_t pid;
    struct q_entry user_count;

    key = ftok("keyfile", 1);
    qid = msgget(key, 0600|IPC_CREAT);

    if(msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT) < 0){
        id_counter = 1;
        total_user = 1;
        message_counter = 2;

        user_count.mtype = 1;
        user_count.id_counter = id_counter;
        user_count.total_user = total_user;
        user_count.message_counter = message_counter;
        id = id_counter;
        msgsnd(qid, &user_count, 3*sizeof(int), 0);
    }
    else{
        id_counter = user_count.id_counter + 1;
        total_user = user_count.total_user + 1;
        message_counter = user_count.message_counter;

        user_count.mtype = 1;
        user_count.id_counter = id_counter;
        user_count.total_user = total_user;
        user_count.message_counter = message_counter;
        id = id_counter;
        msgsnd(qid, &user_count, 3*sizeof(int), 0);
    }

    printf("id = %d\n", id);

    pid = fork();
    if(pid == 0){
        receiver(id, qid);
    }
    else{
        waitpid(pid, 0, WNOHANG);
        sender(id, qid);
    }

    msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT);
    id_counter = user_count.id_counter;
    total_user = user_count.total_user;
    message_counter = user_count.message_counter;

    user_count.mtype = 1;
    user_count.id_counter = id_counter;
    user_count.total_user = total_user - 1;
    user_count.message_counter = message_counter;
    msgsnd(qid, &user_count, 3*sizeof(int), 0);

    if(user_count.total_user == 0){
        printf("no user exists\n");
        msgctl(qid, IPC_RMID, 0);
    }

    exit(1);
}

20181210 ์ตœ์ข… ์„ค๊ณ„๋„ ๊ธฐ๋ฐ˜ ์ฝ”๋“œ

  • talk_wait, talk_start ๋ถ€๋ถ„ ์ˆ˜์ •
    • 2๋ช…์œผ๋กœ ๋์„ ๋•Œ talk_start๋ฅผ ๋ฉ”์„ธ์ง€๋กœ ๋ณด๋‚ด์„œ ๋‹ค๋ฅธ ํ•œ ์ชฝ์—์„œ๋„ ์ฑ„ํŒ…์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ์„ค์ •. 3๋ช… ์ด์ƒ์ผ ๋•Œ๋Š” ํ˜ผ์ž๋งŒ ์ถœ๋ ฅ.
  • ๊ฐœ์„ ์‚ฌํ•ญ
    • ๊ทผ๋ฐ talk_start ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด 2๋ช… ์งธ talk_start๋ผ๊ณ  ์ธ์‹ํ•ด์„œ ์ „์ฒด ๋‹ค id ์ถœ๋ ฅ ์—†์ด talk_start๋งŒ ์ถœ๋ ฅ
    • ์„ค๊ณ„๋„์— talk_start ๋ฉ”์„ธ์ง€ ๋ณด๋‚ด๋Š”๊ฑธ ์ž‘์„ฑ ์•ˆ ํ–ˆ์Œ
#define BUFSIZE 512

int id_counter, total_user, message_counter;

struct q_entry{
    long mtype;
    int id_counter;
    int total_user;
    int message_counter;
};

struct q_data{
    long mtype;
    int id;
    char mtext[BUFSIZE];
};

void receiver(int id, int qid){
    struct q_entry user_count;
    struct q_data user_message;

    while(msgrcv(qid, &user_message, sizeof(struct q_data), message_counter, 0) > 0){
        if(user_message.id != id){
            if(strcmp(user_message.mtext, "talk_start") == 0){
                printf("talk_start\n");
            }
            else{
                printf("%d : %s\n", user_message.id, user_message.mtext);
            }
        }
        else{
            if (strcmp(user_message.mtext, "talk_quit") == 0) {
                exit(1);
            }
        }
        message_counter++;
    }
    exit(1);
}

void sender(int id, int qid){
    int i;
    char buffer[BUFSIZE];
    struct q_entry user_count;
    struct q_data user_message;

    while(gets(buffer)) {
        msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT);
        user_count.mtype = 1;
        id_counter = user_count.id_counter;
        total_user = user_count.total_user;
        message_counter = user_count.message_counter;

        if ((strcmp(buffer, "talk_quit") == 0)) {
            for(i=0;i<total_user;i++){
                user_message.mtype = message_counter;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }

            user_count.mtype = 1;
            message_counter++;
            user_count.message_counter = message_counter;
            msgsnd(qid, &user_count, 3*sizeof(int), 0);

            return;
        }
        else{
            if(total_user == 1){
                printf("talk_wait ... \n");
            }

            for(i=0;i<total_user;i++){
                user_message.mtype = message_counter;
                user_message.id = id;
                strcpy(user_message.mtext, buffer);
                msgsnd(qid, &user_message, sizeof(struct q_data), 0);
            }

            user_count.mtype = 1;
            message_counter++;
            user_count.message_counter = message_counter;
            msgsnd(qid, &user_count, 3*sizeof(int), 0);
        }
    }
    return;
}

int main(int argc, char **argv){
    int i, id, qid;
    key_t key;
    pid_t pid;
    struct q_entry user_count;
    struct q_data user_message;

    key = ftok("keyfile", 1);
    qid = msgget(key, 0600|IPC_CREAT);

    //์ฒ˜์Œ ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ ๋ฉ”์„ธ์ง€ ํ์— ๋ฉ”์„ธ์ง€๊ฐ€ ์—†๋Š” ์ƒํƒœ์ด๋‹ˆ๊นŒ, msgrcv๊ฐ€ ์‹คํŒจ๋ฅผ ํ•˜๊ฒŒ๋œ๋‹ค
    if(msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT) < 0){
        id_counter = 1;
        total_user = 1;
        message_counter = 2;

        user_count.mtype = 1;
        user_count.id_counter = id_counter;
        user_count.total_user = total_user;
        user_count.message_counter = message_counter;
        id = id_counter;
        msgsnd(qid, &user_count, 3*sizeof(int), 0);
    }
    else{
        id_counter = user_count.id_counter + 1;
        total_user = user_count.total_user + 1;
        message_counter = user_count.message_counter;

        user_count.mtype = 1;
        user_count.id_counter = id_counter;
        user_count.total_user = total_user;
        user_count.message_counter = message_counter;
        id = id_counter;
        msgsnd(qid, &user_count, 3*sizeof(int), 0);
    }

    printf("id = %d\n", id);

    if(total_user == 1){
        printf("talk_wait ... \n");
    }
    else if(total_user == 2){
        //๋ณธ์ธ id์˜ receiver, sender ์‹คํ–‰๋˜๊ณ  ์žˆ์ง€ ์•Š์•„์„œ ์ž๊ธฐ ์ž์‹ ์€ ๋ฏธ๋ฆฌ ์ถœ๋ ฅํ•ด์คŒ
        printf("talk_start\n");

        msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT);
        user_count.mtype = 1;
        id_counter = user_count.id_counter;
        total_user = user_count.total_user;
        message_counter = user_count.message_counter;

        user_message.mtype = message_counter;
        user_message.id = id;
        strcpy(user_message.mtext, "talk_start");
        msgsnd(qid, &user_message, sizeof(struct q_data), 0);

        user_count.mtype = 1;
        message_counter++;
        user_count.message_counter = message_counter;
        msgsnd(qid, &user_count, 3*sizeof(int), 0);
    }
    else if(total_user > 2){
        printf("talk_start\n");
    }

    pid = fork();

    if(pid == 0){
        receiver(id, qid);
    }
    else{
        //๊ตณ์ด ์•ˆ ํ•ด์ค˜๋„ ๋œ๋‹ค๊ณ  ํ–ˆ์Œ
        //waitpid(pid, 0, WNOHANG);
        sender(id, qid);
    }

    msgrcv(qid, &user_count, 3*sizeof(int), 1, IPC_NOWAIT);
    id_counter = user_count.id_counter;
    total_user = user_count.total_user;
    message_counter = user_count.message_counter;

    user_count.mtype = 1;
    user_count.id_counter = id_counter;
    user_count.total_user = total_user - 1;
    user_count.message_counter = message_counter;
    msgsnd(qid, &user_count, 3*sizeof(int), 0);

    //๊ต์ˆ˜๋‹˜ ๋ง์”€์œผ๋กœ๋Š” ๊ตณ์ด pid(receiver)๋ฅผ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ WNOHANG์œผ๋กœ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ™•์ธ ์•ˆ ํ•ด์ค˜๋„ ๋œ๋‹ค๊ณ  ํ•ด์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋บ์Œ
    waitpid(pid, 0, 0);

    if(user_count.total_user == 0){
        msgctl(qid, IPC_RMID, 0);
    }

    exit(1);
}

Producer / Consumer Problem with C

#define BUFFER_SIZE 5
#define EMPTY_ID 0
#define FULL_ID 1
#define MUTEX_ID 2
#define NSEM_SIZE 3

#define SHM_KEY 9
#define SEM_KEY "."

static struct sembuf downEmpty = { EMPTY_ID, -1, 0 };
static struct sembuf upEmpty = { EMPTY_ID, 1, 0 };
static struct sembuf upFull = { FULL_ID, 1, 0 };
static struct sembuf downFull = { FULL_ID, -1, 0 };
static struct sembuf downMutex = { MUTEX_ID, -1, 0 };
static struct sembuf upMutex = { MUTEX_ID, 1, 0 };

int *create_shared_mem_buffer();
int create_semaphore_set();
int get_buffer_size(int *sbuff);
void clear_buffer(int *sbuf);

// producer
void insert_item(int item, int semid, int *shared_buffer) {
    int index = get_buffer_size(shared_buffer);
    shared_buffer[index] = item;
}

int produce_item() {
    return 0xFF; // nothing dynamic just write a static integer a slot
}

int main(int argc, const char *argv[]) {
    int *shared_buffer = create_shared_mem_buffer();
    int semid = create_semaphore_set();

    clear_buffer(shared_buffer); // prepare buffer for jobs

    int item = 0;

    while (1) {
        item = produce_item();
        semop(semid, &downEmpty, 1);
        semop(semid, &downMutex, 1);
        insert_item(item, semid, shared_buffer);
        debug_buffer(shared_buffer);
        semop(semid, &upMutex, 1);
        semop(semid, &upFull, 1);
    }

    return EXIT_SUCCESS;
}


// consumer
void consume_item(int item) {
    // do something with item
}

int remove_item(int semid, int *shared_buffer) {
    int index = get_buffer_size(shared_buffer) - 1;
    int item = shared_buffer[index];
    shared_buffer[index] = 0x00;
    return item;
}

int main(int argc, const char *argv[])
{
    int *shared_buffer = create_shared_mem_buffer();
    int semid = create_semaphore_set();

    int item = 0;

    while(1) {
        semop(semid, &downFull, 1);
        semop(semid, &downMutex, 1);
        item = remove_item(semid, shared_buffer);
        debug_buffer(shared_buffer);
        semop(semid, &upMutex, 1);
        semop(semid, &upEmpty, 1);
        consume_item(item);
    }

    return EXIT_SUCCESS;
}

/**
 * returns current size of shared buffer
 */
int get_buffer_size(int *sbuff) {
    int i = 0;
    int counter = 0;
    for (i = 0; i < BUFFER_SIZE; ++i) {
        if (sbuff[i] == 0xFF) {
            counter++;
        }
    }
    return counter;
}

void debug_buffer(int *sbuff) {
    int i = 0;
    for (i = 0; i < BUFFER_SIZE; ++i) {
        if (sbuff[i] == 0xFF) printf("1");
    }
    printf("\n");
}

/**
 * returns a pointer to a shared memory buffer that the
 * producer can write to.
 */
int *create_shared_mem_buffer() {
    int *shmaddr = 0; /* buffer address */
    key_t key = SHM_KEY; /* use key to access a shared memory segment */

    int shmid = shmget(key, BUFFER_SIZE, IPC_CREAT | SHM_R | SHM_W); /* give create, read and write access */
    if (errno > 0) {
        perror("failed to create shared memory segment");
        exit (EXIT_FAILURE);
    }

    shmaddr = (int*)shmat(shmid, NULL, 0);
    if (errno > 0) {
        perror ("failed to attach to shared memory segment");
        exit (EXIT_FAILURE);
    }

    // clean out garbage memory in shared memory
    return shmaddr;
}

/**
 * only used in the producer to clean out garbage memory when
 * constructing initial buffer.
 */
void clear_buffer(int *sbuff) {
    int i = 0;
    for (i = 0; i < BUFFER_SIZE; ++i) sbuff[i] = 0x00;
}

/**
 * create FULL and EMPTY semaphores
 */
int create_semaphore_set() {
    key_t key = ftok(SEM_KEY, 'E');

    int semid = semget(key, NSEM_SIZE, 0600 | IPC_CREAT);
    if (errno > 0) {
        perror("failed to create semaphore array");
        exit (EXIT_FAILURE);
    }

    semctl(semid, FULL_ID, SETVAL, 0);
    if (errno > 0) {
        perror("failed to set FULL semaphore");
        exit (EXIT_FAILURE);
    }

    semctl(semid, EMPTY_ID, SETVAL, BUFFER_SIZE);
    if (errno > 0) {
        perror("failed to set EMPTY sempahore");
        exit (EXIT_FAILURE);
    }

    semctl(semid, MUTEX_ID, SETVAL, 1);
    if (errno > 0) {
        perror("failed to create mutex");
    }

    return semid;
}
  • producer / consumer problem implemented with circular buffer in C.
/*
 * The Bounded Buffer (aka Producer/Consumer) problem.
 * Demonstrates the UNIX / LINUX fork, shared memory, and semaphores.
 *
 * shmget - gets and returns a shared memory segment -- called only once.
 * shmat - attaches to the shared memory segment created by shmget; called by
 *	   all processes wishing to use the shared memory.
 * semop - performs operations on the shared memory: uses a sembuf structure:
 *	   unsigned short	sem_num;	semaphore number
 *	   short		sem_op;		semaphore operation
 *	   short		sem_flg;	operation flags
 *
 *	   A binary semaphore (i.e., available or not available) is used to
 *	   enforce mutual exclusion.  It is initialized to 1 (sem_op = 1).
 *	   A counting semaphore (used here to guarantee either spaces or
 *	   elements in the buffer) is initialized to the number of available
 *	   resources (the number of slots in the buffer in this example).
 *	   The semaphore is acquired by setting sem_op = -1 (if the current
 *	   semaphore value is >0, the count is decremented and the process
 *	   proceeds; if the semaphore value is 0, the process suspends).
 *	   The semaphore is released by setting sem_op = 1, which increments
 	   the semaphore value (this also resumes any suspended processes).
 */

/* The circular buffer is managed by two values:
 * a front ponter that points to the buffer location where the next
 * element will be inserted (by a producer); and
 * a back pointer from whence the next element will be removed (by a consumer).
 * These values are stored in a array of two integers in shared memory,
 * which is accessed by the symbolic constants defined below.
 * The current circular buffer has a capacity of 10.
 */

enum { FRONT, BACK, BUF_SIZE = 10 };

void producer(int);
void consumer(int);
void debug();

/* The id's are inherited by the children after the fork. */

/* shared memory ids */
int	var_id;		/* shared memory holding counter, front, and back */
int	buf_id;		/* buffer shared memroy segment */

/* semaphore id.
 * The semaphore id below will represent 3 separate semaphores in an array:
 * 0: counting semaphore, which is the number of free spaces in the buffer.
 * 1: counting semaphore, which is the number of elements in the buffer.
 * 2: binary semaphore, which enforces mutual exclusion to critical sections.
 */

int	sem_id;		/* semaphore id */

int main(int argc, char* argv[]) {
    int	i;
    int*	vars;			/* array of shared mem front & back  */
    struct	sembuf	init_sm[] = {		/* initialize the semaphores */
            { 0, BUF_SIZE, IPC_NOWAIT },	/* init # spaces = BUF_SIZE  */
            { 1, 0, IPC_NOWAIT },		/* init # elements = 0	     */
            { 2, 1, IPC_NOWAIT }		/* init mutual exclusion = 1 */
    };

    /* initialize the buffer control variables: front and back	     */
    var_id = shmget(IPC_PRIVATE, 2 * sizeof(int), S_IRUSR | S_IWUSR);
    vars = (int *)shmat(var_id, 0, 0);
    vars[FRONT] = vars[BACK] = 0;

    /* initialize the buffer */
    buf_id = shmget(IPC_PRIVATE, BUF_SIZE * sizeof(int), S_IRUSR | S_IWUSR);

    /* initialize the semaphores */
    sem_id = semget(IPC_PRIVATE, 3, S_IRUSR | S_IWUSR);
    semop(sem_id, init_sm, 3);

    /* Spawn all concurrent processes.
     * fork returns the child's pid to the parent and 0 to the child.
     * the following loop starts five new child processes and assigns
     * them the roles of producer or consumer.
     */
    for (i = 0; i < 5; i++) {
        int	pid = fork();

        if (pid == 0 && i < 3)
            producer(i);
        else if (pid == 0)
            consumer(i);
        /*else pid == 0, which implies the parent process --
        it loops around to start the next child.*/
    }

    /* 5 processes were started - wait for five processes to finish */
    for (i = 0; i < 5; i++) {
        wait(NULL);
        debug();
    }

    return 0;
}


/*
 * Producer processes "produce" a pseudo-random number and simulates the
 * time needed to produce something by sleeping for that number of seconds.
 * After awakening, they attempt to acquire a semaphore lock, waiting if it's
 * not available.  After placing the pseudo-random number in the shared memory,
 * they releases the lock.
 */
void producer(int id) {
    int	i;
    char	obuf[512];
    int*	vars;
    int*	buffer;
    struct	sembuf	acquire[] = {{ 0, -1, 0 }, { 2, -1, SEM_UNDO }};
    struct	sembuf	release[] = {{ 1, 1, 0 }, { 2, 1, SEM_UNDO }};

    vars = (int *)shmat(var_id, 0, 0);	/* attach to buffer vars */
    buffer = (int *)shmat(buf_id, 0, 0);	/* attach to the buffer */

    fprintf(stderr, "Producer starting\n");
    for (i = 0; i < 10; i++) {
        int	prod = rand() % 8;
        sleep(prod);

        /* critical section -- see section 6.2 */
        semop(sem_id, acquire, 2);	/* buffer not full	     */

        buffer[vars[FRONT]] = prod;
        vars[FRONT] = (vars[FRONT] + 1) % BUF_SIZE;

        semop(sem_id, release, 2);	/* buffer has 1 more element */
        /* end critical section */

        sprintf(obuf, "producer %d %d\n", id, prod);
        write(1, obuf, strlen(obuf));
    }
    fprintf(stderr, "producer %d exiting\n", id);
    exit(0);
}


/*
 * Consumer processes simulates the time needed to consume something by
 * sleeping for a pseudo-random amount of time.
 * After awakening, they attempt to acquire a semaphore lock, waiting if it's
 * not available.  After removing a pseudo-random number from the buffer in the
 * shared memory, they releases the lock.
 */
void consumer(int id) {
    int	i;
    char	obuf[512];
    int*	vars;
    int*	buffer;
    struct	sembuf	acquire[] = {{ 1, -1, 0 }, { 2, -1, SEM_UNDO }};
    struct	sembuf	release[] = {{ 0, 1, 0 }, { 2, 1, SEM_UNDO }};

    vars = (int *)shmat(var_id, 0, 0);	/* attach to buffer vars */
    buffer = (int *)shmat(buf_id, 0, 0);	/* attach to the buffer */

    fprintf(stderr, "Consumer starting\n");
    for (i = 0; i < 15; i++) {
        int	consume;
        sleep(rand() % 4);

        /* critical section -- see section 6.2 */
        debug();
        semop(sem_id, acquire, 2);	/* buffer not empty 	   */

        consume = buffer[vars[BACK]];
        vars[BACK] = (vars[BACK] + 1) % BUF_SIZE;

        semop(sem_id, release, 2);	/* buffer has 1 more space */
        /* end critical section */

        sprintf(obuf, "consumer %d %d\n", id, consume);
        write(1, obuf, strlen(obuf));
    }
    fprintf(stderr, "consumer %d exiting\n", id);
    exit(0);
}

/*
 * prints the semaphore values of the three programs semaphores.
 */
void debug()
{
    unsigned short	semvals[3];
    union semun	arg;
    arg.array = semvals;
    semctl(sem_id, 0, GETALL, arg);
    printf("\t%d\t%d\t%d\n", semvals[0], semvals[1], semvals[2]);
}