#include <fcntl.h> // 파일 제어를 위한 함수들을 사용하기 위한 헤더 파일 (open, close)
#include <sys/types.h> // 데이터 타입 정의를 위한 헤더 파일
#include <unistd.h> // POSIX 운영 체제 API (read, write, close)
#define BSIZE 512 // 읽고 쓰는 버퍼의 크기를 정의
#define FPERM 0644 // 생성되는 파일의 권한 설정 (소유자는 읽기+쓰기, 그룹과 다른 사용자는 읽기만 가능)
int main(int argc, char *argv[])
{
int fd1, fd2; // 파일 디스크립터 저장 변수
char buf[BSIZE]; // 데이터 전송을 위한 버퍼
ssize_t size_sum = 0; // 총 쓰여진 바이트 수를 저장할 변수
// 첫 번째 인자로 주어진 파일을 읽기 전용으로 열기
if ((fd1 = open(argv[1], O_RDONLY)) < 0)
{
perror("fd1 error"); // 파일 열기 실패 시 오류 메시지 출력
exit(1); // 프로그램 비정상 종료
}
// 두 번째 인자로 주어진 파일을 쓰기 전용, 파일이 없으면 생성, 파일이 있으면 내용을 지우고 새로 시작하기로 열기
if ((fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FPERM)) < 0)
{
perror("fd2 error"); // 파일 열기 실패 시 오류 메시지 출력
exit(1); // 프로그램 비정상 종료
}
// fd1 파일에서 BSIZE 만큼의 데이터를 읽어 buf에 저장하고, 읽은 바이트 수를 반환
while ((read_content = read(fd1, buf, BSIZE)) > 0)
{
ssize_t bytes_written;
// fd2 파일에 buf의 내용을 read_content 만큼 쓰고, 쓰여진 바이트 수를 반환
bytes_written = write(fd2, buf, read_content);
if (bytes_written == -1)
{
perror("write error"); // 쓰기 실패 시 오류 메시지 출력
}
size_sum += bytes_written; // 쓰여진 바이트 수를 누적
}
// 열려 있는 파일 디스크립터들을 닫기
close(fd1);
close(fd2);
// 총 복사된 바이트 수를 화면에 출력
printf("\"Totally, %ld bytes were copied.\" \n", size_sum);
}
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
#include <time.h>
#define BSIZE 512 // 버퍼 크기 정의
#define FPERM 0644 // 생성 파일의 퍼미션 설정
int main(int argc, char *argv[])
{
int fd1, fd2; // 파일 디스크립터 변수
char buf[BSIZE]; // 파일에서 읽거나 쓰기 위한 버퍼
ssize_t size_sum = 0; // 읽고 쓴 데이터의 총량을 저장
struct stat statbuf; // 파일의 상태 정보를 저장할 구조체
struct utimbuf fd1_utim; // 파일 타임스탬프 수정을 위한 구조체
char tm_string[50]; // 시간을 문자열로 변환하여 저장할 배열
int stat_result = 0; // stat 함수 결과 저장
int chown_result = 0; // chown 함수 결과 저장
// 첫 번째 파일을 읽기 전용으로 열기
if ((fd1 = open(argv[1], O_RDONLY)) < 0)
{
perror("fd1 error");
exit(1); // 파일 열기 실패 시 에러 메시지 출력 후 종료
}
// 첫 번째 파일의 상태 정보 가져오기
stat_result = stat(argv[1], &statbuf);
if (stat_result == 0)
{
printf("attributes of file \"%s\"\n", argv[1]);
printf("st_dev = %ld\n", statbuf.st_dev); // 장치 번호
printf("st_mode = %o\n", statbuf.st_mode); // 파일 모드
printf("st_uid = %ld\n", statbuf.st_uid); // 소유자 UID
printf("st_gid = %ld\n", statbuf.st_gid); // 그룹 ID
printf("st_size = %ld\n", statbuf.st_size); // 파일 크기
printf("st_mtime = %ld\n", statbuf.st_mtime); // 마지막 수정 시간
struct tm *tm = localtime(&statbuf.st_mtime); // 시간 구조체로 변환
strftime(tm_string, sizeof(tm_string), "%Y/%m/%d %H:%M:%S", tm); // 시간을 문자열로 포맷
printf("modified time = %s\n", tm_string);
fd1_utim.actime = statbuf.st_atime; // 접근 시간 설정
fd1_utim.modtime = statbuf.st_mtime; // 수정 시간 설정
}
else
{
perror("stat error"); // stat 실패 시 에러 처리
}
// 두 번째 파일을 쓰기 전용, 생성, 내용 삭제 모드로 열기
if ((fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FPERM)) < 0)
{
perror("fd2 error");
exit(1); // 파일 열기 실패 시 에러 메시지 출력 후 종료
}
chmod(argv[2], statbuf.st_mode); // 파일 모드 변경
chown_result = chown(argv[2], statbuf.st_uid, statbuf.st_gid); // 파일 소유자와 그룹 변경
utime(argv[2], &fd1_utim); // 파일의 접근 및 수정 시간 설정
close(fd1); // 첫 번째 파일 디스크립터 닫기
close(fd2); // 두 번째 파일 디스크립터 닫기
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t child_pid;
// 자식 프로세스 생성
child_pid = fork();
if (child_pid < 0)
{
// fork 실패 시 에러 메시지 출력 및 비정상 종료
fprintf(stderr, "fork failed\n");
exit(-1);
}
else if (child_pid == 0)
{
// 자식 프로세스
// "/bin/ls"를 실행하여 현재 디렉토리 내용 출력
execlp("/bin/ls", "ls", NULL);
// execlp가 실패하여 리턴되면 실행됨
perror("execlp failed"); // execlp 실패 시 오류 메시지 출력
exit(1); // 오류가 발생했으므로 1을 반환하며 종료
}
else
{
// 부모 프로세스
// 자식 프로세스의 완료를 대기
wait(NULL);
// 자식 프로세스 완료 후 메시지 출력
printf("Child Completed\n");
// 부모 프로세스 정상 종료
exit(0);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main() {
key_t key = 1234; // 공유 메모리 키
int shm_id;
char *shared_memory;
// 공유 메모리 생성 또는 접근
shm_id = shmget(key, 1024, IPC_CREAT | 0666);
if (shm_id < 0) {
perror("shmget failed");
exit(1);
}
printf("Shared memory ID: %d\n", shm_id);
// 공유 메모리를 현재 프로세스의 주소 공간에 연결
shared_memory = (char *)shmat(shm_id, NULL, 0);
if (shared_memory == (char *)-1) {
perror("shmat failed");
exit(1);
}
// 공유 메모리에 데이터 쓰기
char *data = "Hello, Shared Memory!";
strncpy(shared_memory, data, strlen(data));
shared_memory[strlen(data)] = '\0'; // 문자열 종료 널 문자 추가
printf("Written to shared memory: %s\n", shared_memory);
// 공유 메모리에서 데이터 읽기
printf("Read from shared memory: %s\n", shared_memory);
// 공유 메모리 연결 해제
if (shmdt(shared_memory) == -1) {
perror("shmdt failed");
exit(1);
}
// 공유 메모리 삭제
if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
perror("shmctl failed");
exit(1);
}
return 0;
}
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printf("Welcome to my remote shell server!\n"); // 원격 쉘 서버에 오신 것을 환영한다는 메시지 출력
// 공유 메모리 파일 생성
int shm_fd = shm_open(argv[1], O_CREAT | O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open"); // shm_open 호출 실패 시 에러 메시지 출력
return EXIT_FAILURE;
}
// 공유 메모리 파일의 크기를 512바이트로 설정
if (ftruncate(shm_fd, 512) == -1)
{
perror("ftruncate"); // ftruncate 호출 실패 시 에러 메시지 출력
return EXIT_FAILURE;
}
// 공유 메모리를 현재 주소 공간에 매핑
void * shm = mmap(0, 512, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm == MAP_FAILED)
{
perror("mmap"); // mmap 호출 실패 시 에러 메시지 출력
return EXIT_FAILURE;
}
// 공유 메모리를 0으로 초기화 (예: shm[0] = 0;)
memset(shm, 0, 512);
// 반복
while(1)
{
printf("Waiting for a command ...\n"); // 명령어를 기다린다는 메시지 출력
// shm에 값이 들어올 때까지 usleep(100000)을 반복 호출
while (*(char *)shm == 0) { usleep(100000); }
// 명령 수행
// 여기에 명령을 수행하는 코드가 들어가야 합니다.
}
// 매핑 해제
if (munmap(shm, 512) == -1)
{
perror("munmap"); // munmap 호출 실패 시 에러 메시지 출력
}
// 공유 메모리 파일 제거
if (shm_unlink(argv[1]) == -1)
{
perror("shm_unlink"); // shm_unlink 호출 실패 시 에러 메시지 출력
}
// 작별 인사 메시지 출력
printf("Good bye\n");
return EXIT_SUCCESS; // 프로그램 종료
}
#include <sys/mman.h> // 메모리 관리 함수 포함
#include <sys/stat.h> // 파일 상태 정보 함수 포함
#include <fcntl.h> // 파일 제어 함수 포함
#include <unistd.h> // POSIX 시스템 호출 함수 포함
// main 함수 정의, 공유 메모리 파일 이름은 argv[1]을 통해 받음
int main(int argc, char **argv)
{
// 공유 메모리 파일 열기
int shm_fd = shm_open(argv[1], O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open 실패"); // shm_open 호출 실패 시 에러 메시지 출력
return 1;
}
// 공유 메모리를 현재 주소 공간에 매핑
void *shm = mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm == MAP_FAILED)
{
perror("mmap 실패"); // mmap 호출 실패 시 에러 메시지 출력
return 1;
}
// 무한 반복
while(1)
{
// 공유 메모리의 첫 바이트가 0이 아닐 때까지 대기
// 서버에서 메모리를 비워줄 때까지 대기
while (*(char *)shm != 0) { usleep(100000); }
char cmd[100];
// 텍스트 라인으로 명령어 입력 받기 (fgets() 사용)
// 명령어가 비어있지 않은 경우
printf("$ "); // 명령어 프롬프트 출력
if (fgets(cmd, sizeof(cmd), stdin) == NULL)
{
perror("명령어 읽기 실패"); // fgets 호출 실패 시 에러 메시지 출력
continue;
}
cmd[strlen(cmd) - 1] = '\0'; // 개행 문자 제거
// 명령어가 "exit"이면 루프 종료
if (strcmp(cmd, "exit") == 0)
break;
// 입력받은 명령어를 공유 메모리 블록에 복사
strncpy(shm, cmd, 512);
// 명령어가 "exit_svr"이면 루프 종료
if (strcmp(cmd, "exit_svr") == 0)
break;
}
// 매핑 해제
if (munmap(shm, 512) == -1)
{
perror("munmap 실패"); // munmap 호출 실패 시 에러 메시지 출력
return 1;
}
return 0; // 프로그램 정상 종료
}
msgget() 함수를 사용하여 메시지 큐를 생성 또는 접근합니다.
msgsnd() 함수를 사용하여 메시지 큐에 메시지를 보냅니다.
msgrcv() 함수를 사용하여 메시지 큐에서 메시지를 받습니다.
msgctl() 함수를 사용하여 메시지 큐를 제어하고, 필요할 경우 제거합니다.
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct msgbuf {
long mtype; // 메시지 타입
char mtext[200]; // 메시지 데이터
};
int main() {
key_t key;
int msgid;
struct msgbuf msg;
// 메시지 큐 키 생성
key = ftok("filepath", 65);
if (key == -1) {
perror("ftok failed");
exit(1);
}
// 메시지 큐 생성 또는 접근
msgid = msgget(key, 0666 | IPC_CREAT);
if (msgid == -1) {
perror("msgget failed");
exit(1);
}
// 메시지 보내기
msg.mtype = 1;
strcpy(msg.mtext, "Hello, this is a message.");
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
perror("msgsnd failed");
exit(1);
}
printf("Sent message: %s\n", msg.mtext);
// 메시지 받기
if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
perror("msgrcv failed");
exit(1);
}
printf("Received message: %s\n", msg.mtext);
// 메시지 큐 제거
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl failed");
exit(1);
}
return 0;
}
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFFER_SIZE 25 // 버퍼 크기를 25로 정의
#define MAX_READ 512 // 한 번에 읽을 수 있는 최대 길이를 512로 정의
#define READ_END 0 // 파이프의 읽기 끝을 나타내는 상수
#define WRITE_END 1 // 파이프의 쓰기 끝을 나타내는 상수
int main(void) {
char* write_msg = "apple narang cider such nice good hi bye";
char read_msg[MAX_READ];
int fd[2];
pid_t pid;
// 파이프 생성
if (pipe(fd) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
// 자식 프로세스 생성
pid = fork();
if (pid < 0) { // fork 실패 시
fprintf(stderr, "Fork Failed");
return 1;
}
if (pid > 0)
{ // 부모 프로세스
// 읽기용 파이프 끝 닫기
close(fd[READ_END]);
int writen_byte = 0;
printf("%d\n", strlen(write_msg));
while(writen_byte < strlen(write_msg))
{
if(BUFFER_SIZE > strlen(write_msg)-writen_byte+1)
{
writen_byte += write(fd[WRITE_END], write_msg+writen_byte, strlen(write_msg)-writen_byte+1);
}
else
{
// 파이프에 데이터 쓰기
writen_byte += write(fd[WRITE_END], write_msg+writen_byte, BUFFER_SIZE);
}
printf("%d\n", writen_byte);
}
// 쓰기용 파이프 끝 닫기
close(fd[WRITE_END]);
}
else
{ // 자식 프로세스
// 쓰기용 파이프 끝 닫기
close(fd[WRITE_END]);
int read_byte = 0;
while(read_byte < strlen(write_msg))
{
// 파이프에서 데이터 읽기
read_byte += read(fd[READ_END], read_msg, BUFFER_SIZE);
read_msg[BUFFER_SIZE] = '\0';
printf("read !! %s\n", read_msg);
}
// 읽기용 파이프 끝 닫기
close(fd[READ_END]);
}
return 0;
}
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS 3 // 생성할 쓰레드의 수 정의
// 쓰레드 함수
void* thread_func(void* arg) {
int thread_id = *((int*)arg);
printf("Hello from thread %d\n", thread_id);
pthread_exit(NULL);
}
int main(void) {
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int scope;
int policy;
int thread_args[NUM_THREADS];
// 쓰레드 속성 초기화
if(pthread_attr_init(&attr) != 0) {
fprintf(stderr, "Failed to initialize thread attributes\n");
return 1;
}
// 쓰레드 속성에 스코프 설정
if(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0) {
fprintf(stderr, "Unable to set scope.\n");
}
// 스케줄링 정책을 FIFO로 설정
if(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
fprintf(stderr, "Unable to set policy.\n");
}
// 여러 개의 쓰레드 생성
for (int i = 0; i < NUM_THREADS; i++) {
thread_args[i] = i; // 쓰레드별로 고유 아규먼트 설정
if(pthread_create(&threads[i], &attr, thread_func, (void*)&thread_args[i]) != 0) {
fprintf(stderr, "Failed to create thread %d\n", i);
return 1;
}
}
// 설정된 스코프와 스케줄링 정책 확인
if(pthread_attr_getscope(&attr, &scope) != 0) {
fprintf(stderr, "Unable to get scope.\n");
} else {
printf("PTHREAD SCOPE: %s\n", scope == PTHREAD_SCOPE_SYSTEM ? "SYSTEM" : "PROCESS");
}
if(pthread_attr_getschedpolicy(&attr, &policy) != 0) {
fprintf(stderr, "Unable to get policy.\n");
} else {
if(policy == SCHED_OTHER)
printf("SCHED OTHER\n");
else if(policy == SCHED_RR)
printf("SCHED RR\n");
else if(policy == SCHED_FIFO)
printf("SCHED FIFO\n");
}
// 모든 쓰레드가 종료될 때까지 기다림
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
// 쓰레드 속성 객체 파괴
pthread_attr_destroy(&attr);
return 0;
}
pthread_cancel(tid);
pthread_t pthread_setcanceltype(int type, int* oldtype)
- PTHREAD_CANCEL_ASYCHRONUS : 호출 시 즉시 종료
- PTHREAD_CANCEL_DEFERED : pthread_testcancel() 호출지점 이후 종료
pthread_t pthread_setcancelstate(int state, int* oldstate)
- PTHREAD_CANCEL_DISABLE : 취소 요청을 받더라도 즉시 취소되지 않고,
취소 요청이 보류(pending) 상태
- PTHREAD_CANCEL_ENABLE : 스레드는 취소 요청을 받는 즉시 해당 요청을 처리
(PTHREAD_CANCEL_ASYNCHRONOUS / PTHREAD_CANCEL_DEFERRED)
#include <signal.h>
#include <unistd.h>
#define SIGINT 2 /* interrupt */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
void sig_handler(int signo);
// press CTRL-\ to terminate this program
int main()
{
int i = 0;
signal(SIGINT, (void *)sig_handler); // SIGINT
while(1)
{
printf("%d\n", i++);
sleep(1);
}
return 1;
}
void sig_handler(int signo)
{
printf("SIGINT was received!\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THREADS 3
__thread int tls;
int global;
void *func(void *arg)
{
int num = (int) arg;
tls = num;
global = num;
sleep(1);
printf("Thread = %d tls = %d global = %d\n",num, tls, global);
}
int main()
{
int ret;
pthread_t thread[THREADS];
int num;
for(num = 0; num < THREADS; num++)
{
ret = pthread_create(&thread[num], NULL, &func, (void *)num);
if(ret)
{
printf("error pthread_create\n");
exit(1);
}
}
for(num = 0; num < THREADS; num++)
{
ret = pthread_join(thread[num], NULL);
if(ret)
{
printf("error pthread_join\n");
exit(1);
}
}
return 0;
}
fork() 의 Scope
char text[MAX_LEN];
if (fgets(text, MAX_LEN, stdin) == NULL)
if (strncmp(text, "abcd", 4) == 0)
write(out, text, strlen(text) + 1);
read(in, in_mesg, MAX_LEN);
shared_memory[strlen(data)] = '\0'; // 문자열 종료 널 문자 추가