• 파일락 예제
멀티프로세스 환경에서 락을 걸어두면 파일에 접근 못하게 하는 파일락 예제
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int file_lock(int fd);
int file_unlock(int fd);
int main(){
int fd;
int count = 0;
if((fd=open("flock.txt", O_CREAT | O_RDWR, 0644)) == -1){
perror("open");
exit(1);
}
//파일 락 설정
if(file_lock(fd)== -1){
perror("file_lock");
exit(1);
}
int n;
if((n=read(fd, &count, sizeof(count))) == -1){
perror("open");
exit(1);
}
printf("count : %d\n", count);
count++;
write(fd, &count, sizeof(count));
sleep(10);
if(file_unlock(fd) == -1){
perror("file_unlock");
exit(1);
}
close(fd);
}
int file_lock(int fd){
struct flock lock;
lock.l_type= F_WRLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0; // 파일 전체 락
return fcntl(fd, F_SETLKW, &lock);
}
int file_unlock(int fd){
struct flock lock;
lock.l_type= F_UNLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0; // 파일 전체 락
return fcntl(fd, F_SETLK, &lock);
}
특정 위치만 락 하는 예제
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int file_lock(int fd, int offset);
int file_unlock(int fd, int offset);
int main(int argc, char* argv[])
{
int fd;
char buf[16];
int offset = atoi(argv[1])*16;
if((fd=open("rlock.txt", O_RDWR))==-1){
perror("open");
exit(1);
}
// 파일 lock 을 설정, lock을 설정하지 못하는 경우 -1 반환
if(file_lock(fd, offset)==-1) {
perror("file_lock");
exit(1);
}
int n;
memset(buf, 0, 16);
lseek(fd, offset, SEEK_SET);
if((n=read(fd, buf, 16))==-1) {
perror("read");
exit(1);
}
printf("buf : %s\n", buf);
lseek(fd, offset, SEEK_SET);
sprintf(buf, "%d",atoi(buf)+1);
write(fd, buf, 16);
sleep(10);
if(file_unlock(fd, offset)==-1) {
perror("file_unlock");
exit(1);
}
close(fd);
}
int file_lock(int fd, int offset)
{
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_whence=SEEK_SET;
lock.l_start=offset;
lock.l_len=16;
return fcntl(fd, F_SETLKW, &lock);
}
int file_unlock(int fd, int offset)
{
struct flock lock;
lock.l_type=F_UNLCK;
lock.l_whence=SEEK_SET;
lock.l_start=offset;
lock.l_len=16;
return fcntl(fd, F_SETLK, &lock);
}
• 파일 링크, 심볼릭 링크 예제
system 안에 명령어를 넣으면 터미널에 작성한 것과 같은 기능
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
system("ls -l flock.txt");
printf("-----------------------------\n");
if(link("flock.txt","hlink.txt")==-1){
perror("link");
exit(1);
}
system("ls -l flock.txt hlink.txt");
printf("-----------------------------\n");
if(symlink("flock.txt","slink.txt")==-1){
perror("symlink");
exit(1);
}
system("ls -l flock.txt hlink.txt slink.txt");
return 0;
}
• stat 메서드
stat 파일명 하면 상세 정보를 출력해준다
코드에서는 struct stat으로 상세 정보를 가져온다
stat 구조체의 속성으로 어떤 유형인지, 크기 등등 ls -l 명령어로 확인할 수 있는 정보를 가져올 수 있다
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
if (argc != 2)
{
fprintf(stderr, "Usage : %s filename\n", argv[0]);
exit(1);
}
struct stat fbuf;
if(stat(argv[1], &fbuf) == -1){
perror("stat");
exit(1);
}
printf("inode : %d, size : %ld\n", (int)fbuf.st_ino, fbuf.st_size);
if (S_ISDIR(fbuf.st_mode))
{
printf("Directory\n");
}
else if(S_ISREG(fbuf.st_mode)){
printf("Regular File\n");
}
return 0;
}
• 디렉터리 관련 메서드
인자로 디렉토리를 받아서 정보 보여주는 코드
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage : %s directory name\n", argv[0]);
exit(1);
}
struct stat fbuf;
if (stat(argv[1], &fbuf) == -1)
{
perror("stat");
exit(1);
}
// printf("inode : %d, size : %ld\n", (int)fbuf.st_ino, fbuf.st_size);
DIR *dp;
if (S_ISDIR(fbuf.st_mode))
{
printf("Directory\n");
if((dp = opendir(argv[1])) == -1){
perror("opendir error");
exit(1);
}
struct dirent* dirp;
while (1)
{
dirp = readdir(dp);
if (dirp == NULL) break;
printf("inode : %d, filename : %s", (int)dirp->d_ino, dirp->d_name);
}
closedir(dirp);
}
else if (S_ISREG(fbuf.st_mode))
{
printf("Regular File\n");
}
return 0;
}
• 시간
유닉스의 시간은 1970 1/1 00:00:00이 기준으로 초 단위로 제공한다
초단위로 보여주기
int main(){
struct timeval tv;
gettimeofday(&tv, NULL);
printf("tv_sec : %ld, tv_usec : %ld\n", tv.tv_sec, tv.tv_usec);
}
형식 맞춰서 오늘 날짜 연월일 + 시간 형태로 보여주기
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
int main(){
int i,j ;
time_t rawtime;
struct tm *tm;
char buf[BUFSIZ];
struct timeval mytime;
time(&rawtime);
printf("time : %u\n", (unsigned)rawtime);
gettimeofday(&mytime, NULL);
printf("gettimeofday : %ld/%ld\n", mytime.tv_sec, mytime.tv_usec);
printf("ctime : %s", ctime(&rawtime));
putenv("TZ=PST3PDT");
tzset();
tm = localtime(&rawtime);
printf("asctime : %s", asctime(tm));
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y", tm);
printf("strftime : %s\n",buf);
return 0;
}
• 프로세스!
• 시그널 함수
시그널 핸들러를 이용해서 사용자가 프로세스에 들어가는 시그널을 설정할 수 있다
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
//시그널 핸들러
void int_handler(int signum){
printf("int_handler\n");
}
int main(){
// signal(SIGINT, SIG_IGN); // 인터럽트 무시, ctrl+c 로 종료 무시됨
signal(SIGINT, int_handler); // 사용자가 정의한 시그널 핸들러 호출
for(;;){
printf("signal test\n");
sleep(1);
};
}
- 시그널 함수의 단점
동일한 시그널이 계속 발생하면 이전 시그널을 처리하는 중에는 시그널이 블록되서 다음 시그널이 처리되지 않는다
해결하기 위해서 sigaction 메서드를 사용
• sigaction()
sigaction 메서드를 사용해서 시그널 처리
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
int tmp = 0;
//시그널 핸들러
void int_handler(int signum){
printf("int_handler %d", tmp++);
}
int main(){
struct sigaction sigact, oldsigaction;
sigact.sa_handler = int_handler;
sigfillset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigaction(SIGINT, &sigact, &oldsigaction);
sigaction(SIGINT, &sigact, &oldsigaction); // 사용자가 정의한 시그널 핸들러 호출
for(;;){
printf("signal test\n");
sleep(1);
};
}
- sigaction으로 재정의한 시그널 핸들러 원복
sigaction(SIGQUIT, &oldsigaction, NULL);
'대외활동 > 시스템프로그래밍' 카테고리의 다른 글
프로세스 간 통신(파이프, ipc) (1) | 2024.08.29 |
---|---|
0828 프로세스, 블로킹/논블로킹 (6) | 2024.08.28 |
라즈베리파이 크로스컴파일 설정 (0) | 2024.08.26 |
0826 리눅스 시스템 프로그래밍 (0) | 2024.08.26 |
시험대비 qt c++ 복습 (0) | 2024.08.25 |