-
์ฒซ ํด์ฆ ์ ์ถ ๊ฒฐ๊ณผ
./QUIZ10-10 submitted.c, 13011022.c
-
์์ ์๊ฐ์ ํ์๋ค์ด๋ ์ ์ถํ ๊ฒฐ๊ณผ
./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
-
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 ์ฝ๋ฉ๊น์ง ์์์ผ ํ๊ธฐ, ์์์ผ ์ค๊ธฐ
#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;
}
}
}
}#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๋ก ์ค์ ์ ํด์ฃผ๋ฉด ๋๋ค.
-
์ํ์ ๋งํ์ง๋ง ๋ค์ ํ์ด๋ดค์.
- ๊ทผ๋ฐ ๋ค์ ํ์ด๋ณธ ์ฝ๋์์๋ 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");
}
}-
์ฑํ ํ๋ก๊ทธ๋จ ๋จผ์ ํ ๋ฒ ์ฝ๋ฉํด๋ดค์
- ์ผ๋จ ๋ฉ์ธ์ง ํ๋ง ์ด์ฉํ์ฌ ์ฑํ ์ ์ฐธ์ฌํ ์ฌ๋๋ค์๊ฒ ์ ์์ด๊ณ ์ ์ ๋ฌํ๊ฒ๋ ๋ง๋ค์๋๋ฐ,,,
- ์ค์๊ฐ์ผ๋ก ์ฑํ ์ฐธ์ฌํ ์ธ์์ ํ์ ํด์ฃผ๋ ๊ธฐ๋ฅ์ ๋ ์์ ๋ด์ค์ผํจ.
#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);
}- 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);
}#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]);
}