sys/stat.h
파일의 ‘상태’에 대한 정보를 얻거나 설정
- 해당 파일이 저장된 디바이스 번호
- 해당 파일의 inode 번호
- 해당 파일의 Mode
- 해당 파일 소유자의 User ID
- 해당 파일 소유자의 Group ID
- 해당 파일의 하드 링크 개수
- 해당 파일의 블록 크기
- 해당 파일의 블록 개수
- 해당 파일을 마지막으로 액세스한 시간
- 해당 파일을 마지막으로 편집한 시간
example
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
struct stat buf;
if(argc > 1)
{
printf("Arguments is not allowed! \n");
return 1;
}
printf("argv[0]: %s \n", argv[O]);
stat(argv[0], &buf);
printf("Mode: %lo \n", (unsigned long)buf.st_mode); // Type & Protection
printf("UID: %d \n", (int)buf.st_uid); // User ID of the File
printf("Size: %d \n", (int)buf.st_size); // Size of the File
printf("Modification Time: %d \n", (int)buf.st_mtime); // Latest Modification Time
return 0;
}
Mode는 파일 타입과 접근 허가(=파일 속성)
result
assist@assist-VirtualBox:~/Unix_Programming$ ls -l fstat
-rwxr-xr-xX 1 assist assist 8496 10월 1 19:07 fstat
assist@assist-VirtualBox:~/Unix_Programming$ fstat
argv[®]: fstat
Mode: 100755
UID: 10660
Size: 8496
Modification Time: 1569924462
Mode가 100755라는 의미 중 앞의 100~은 위 그림의 S_IFREG 즉 regular file이라는 의미이다.
하드 링크와 심볼릭 링크
하드 링크 (Hard Link)
- 파일에 대한 별명(alias)
- 파일 이름이 다르다 해도 같은 내용을 가리킴
- 파일의 소유자만이 생성할 수 있음
심볼릭 링크 (Symbolic Link)
- 유닉스에서의 ‘바로가기’
- 누구나 생성가능
- 원본 파일이 없으면 링크가 깨짐
하드 링크 만들기 & 지우기
<unistd.h>
int link(const char *old, const char *new)
- old 파일을 new 파일에 하드 링크
- old와 new는 같은 파일을 가리킴
int unlink(const char *path)
- path로 지정된 하드 링크를 제거
- 마지막 남은 링크인 경우 사실상 파일을 삭제
리턴 값 : 0이면 성공, 아니면 실패
example (mv.c)
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
if(arge != 3)
{
perror("Usage: ./mv <old> <new> \n");
return -1;
}
if(link(argv[1], argv[2]))
{
printf("Link failed. : %s -> %s \n", argv[1], argv[2]);
return -2;
}
/*
if(unlink(argv[1]))
{
printf("Unlink failed. : %s \n", argv[1]);
return -3;
}
*/
printf("File moved: %s -> %s \n", argv[1], argv[2]);
return 0;
}
result
assist@assist-VirtualBox:~/Unitx_Programming$ ls -1 fstat
-rwxr-xr-xX 1 assist assist 8496 10월 1 19:07 fstat
assist@assist-VirtualBox:~/Unix_Programming$ ./mv fstat fstat2
File moved: fstat -> fstat2
assist@assist-VirtualBox:~/Unix_Programming$ ls -l fstat*
-rwxr-xr-x 2 assist assist 8496 10월 1 19:07 fstat
-rw-r--r-- 1 assist assist 558 10월 1 19:07 fstat.c
-rwxr-xr-x 2 assist assist 8496 10월 1 19:07 fstat2
fstat 파일의 link count가 1에서 2로 증가하고, fstat2도 link count가 2인 것을 확인
디렉터리 만들기
<sys/types.h>, <sys/stat.h>
int mkdir(const char *pathname, mode_t mode)
- pathname : 생성할 디렉터리 경로
- mode : 생성할 디렉터리의 권한
- 리턴 값 : 0이면 성공, 아니면 실패
example (md.c)
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char* argv[])
{
int i;
for(i = 1 3; i < argc ; ++i)
mkdir(argv[i], 0777);
return 0;
}
result
assist@assist-VirtualBox:~/Unix_Programming$ ./md dir1 dir2
assist@assist-VirtualBox:~/Unix_Programming$ ls -1
합계 120
-rwxr-xr-x 1 assist assist 8440 10월 1 21:45 cd
-rw-r--r-- 1 assist assist 345 10월 1 22:26 cd.c
drwxr-xr-x 2 assist assist 4096 10월 1 22:30 diri
drwxr-xr-x 2 assist assist 4096 10월 1 22:30 dir2
코드에서 permission을 0777로 작성했으나 생성된 permisison은 0755이다.
이는 defulat umask가 0022이기 때문이다.
system call chmod
chmod(파일명, 권한)
- sys/stat.h 헤더에 포함
- 파일명 : 권한을 바꿀 대상 파일
- 권한 : 덮어쓸 권한을 설정
umask
umask(마스크)
- 파일이나 디렉터리를 만들 때 권한을 마스킹
- 마스크 역시 8진수 형식으로 설정
- 최종 권한 : 0777 & ~마스크
실제 결과는 open()을 해야 확인 가능하다
example (md_umask.c)
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char* argv[])
{
int i;
umask(0000); // mask: 000
for(i = 1 ; i < argc ; ++i)
mkdir(argv[i], 0777);
return 0;
}
result
assist@assist-VirtualBox:~/Unix_Programming$ ./md dir_md
assist@assitst-VirtualBox:~/Unix_Programming$ ./md_umask dir_md_umask
assist@assist-VirtualBox:~/Unix_Programming$ ls -1
합계 88
drwxr-xr-x 2 assist assist 4096 10월 1 20:58 dir_md
drwxrwxrwx 2 assist assist 4096 10월 1 20:58 dir_md_umask
-rwxr-xr-x 1 assist assist 8296 10월 1 20:43 md
-rw-r--r-- 1 assist assist 155 10월 1 26:43 md.c
디렉터리 지우기
<unistd.h>
int rmdir(const char *pathname)
- pathname : 삭제할 디렉터리 경로
디렉터리는 반드시 비어 있어야 함
- 리턴 값 : 0이면 성공, 아니면 실패
example (rm.c)
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int i, res;
dup2(1, 2); // stderr에 stdout 덮어씀
for(i = 1; t < argc ; ++i)
{
res = rmdir(argv[i]);
if(res)
printf ("rmdir for %s failed. \n", argv[i]);
}
return 0;
}
result
unix@unixsystem:~$ ls -1
total 32
drwxr-xr-x 2@ unix unix 4096 Oct 13 20:18 dir1
drwxr-xr-x 2 unix unix 4096 Oct 13 20:18 dir2
-rwxr-xr-x 2 unix unix 5016 Oct 13 20:09 md
-rw-r--r-- 41 unix unix 157 Oct 13 20:08 md.c
-rwxr-xr-x 2 unix unix 5157 Oct 13 20:18 rm
-rw-r--r-- 1 unix unix 215 Oct 13 20:17 rm.c
unix@unixsystem:~$ ./rm diri dir2 dir3
rmdir for dir3 failed.
unix@unixsystem:~$ ls -1
total 24
-rwxr-xr-x 1 unix unix S016 Oct 13 20:09 md
-rw-r--r-- 1 unix unix 157 Oct 13 20:08 md.c
-rpwxr-xr-x% 1 unix unix 5157 Oct 13 20:18 rm
-rw-r--r-- 2 unix unix 215 Oct 13 20:17 rm.c
unix@unixsystem:~$ _
디렉터리 위치 변경
<unistd.h>
int chdir(const char *pathname)
- pathname : 이동할 디렉터리 위치
- 리턴 값 : 0이면 성공, 아니면 실패
- 디렉터리 위치는 현재 프로세스에 한정
int fchdir(int fd)
- fd : 이동할 디렉터리의 파일 서술자
- 나머지는 chdir()과 동일
디렉터리 위치 확인
<unistd.h>
char* getcwd(char *name,size_t size)
- name : 현재 위치를 저장할 포인터이자 리턴 값
- size : name의 크기 (충분히 커야 함)
example (cd.c)
#finclude <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
char name[256];
int i, res;
printf ("Current Dir.: %s \n", getcwd(name, 256));
for(i = 1; i < arge ; ++i)
{
res = chdir(argv[i]);
if(res)
printf("Chdir for %s failed. \n", argv[i]);
else
printf("Current Dir.: %s \n", getcwd(name, 256));
}
return 0;
}
result
unix@unixsystem:~$ ./cd /tmp /var /usr/include ~
Current Dir. : /home/unix
Current Dir. : /tmp
Current Dir. : /var
Current Dir. : /usr/include
Current Dir. : /home/unix
unix@unixsystem:~$ _
디렉터리 엔트리
Unix에서는 모든 것을 파일로 관리함
- 일반 파일, 블록 파일, 디렉터리 파일, 장치 파일…
디렉터리는 특수한 형태의 파일
디렉터리 엔트리는 디렉터리를 표현하는 데에 쓰이는 자료구조
디렉터리에 속한 파일들은 디렉터리 엔트리, 구조체로 관리
디렉터리 엔트리 구조
struct dirent
{
#ifndef __USE_FILEOFFSET64 // 64비트 사용
__ino_t d_ino; // 파일 엔트리 번호(inode)
__off_t d_off; // 파일 오프셋 (offset)
#else // 32비트 사용
__ino64_t d_ino; // inode (64비트 강제)
__off64_t d_off; // offset (64비트강제)
#endif
unsigned short int d_reclen; // 파일 이름의 길이
unsigned char d_type; // 파일 타입
char d_name [256] ; // 파일 이름
};
디렉터리 열기
<dirent.h>
DIR *opendir(const char *pathname)
- pathname : 디렉터리의 경로
- 리턴 값 : NULL이면 실패, 아니면 성공
int closedir(DIR *dirp)
- 열려있던 디렉터리를 닫음
디렉터리 읽기
<dirent.h>
struct dirent *readdir(DIR *dirp)
- dirp : 열려 있는 디렉터리 포인터
- 리턴 값 : 디렉터리 엔트리 (NULL이면 실패)
- 디렉터리의 엔트리를 하나 읽어옴
- 읽은 뒤에는 다음 엔트리로 넘김
void rewinddir(DIR *dirp)
- dirp의 포인터를 처음으로 되돌림
example (list.c)
#include <dirent.h>
#include <stdio.h>
int main(int argc, char* argv[]){
int res, depth = 0;
DIR* dirp;
struct dirent* entry;
if(arge != 2){
perror("Usage: list <path> \n");
return -1;
}
dirp = opendir(argv[1]);
if(dirp == NULL){
perror("Directory cannot be opened. \n");
return -2;
}
while((entry = readdir(dirp)) != NULL)
printf("%101ld : %s \n", entry->d_ino, entry->d_name);
closedir(dirp);
return 0;
}
result
unix@unixsystem:“$ ./list .
570 : ..
293 : md.c
294 : cd.c
450 : cd
452 : list
1055 : .bash_history
4610 : .
321 : rm.c
26205 : .profile
31360 : .bashre
384 : rm
432 : md
33103 : .bash_logout
326 : list.c
unix@unixsystem:~$ —
현재 디렉터리에 대한 inode 번호와 파일명이 모두 표시
(현재와 상위 디렉터리도 표시)
Background에서 작업 수행하기
Ctrl + Z
- 현재 foreground에서 실행 중인 작업을 중지시킴
assist@assist-VirtualBox:~/Unix_Programming$ ./bg Knock! ^Z [1]+ Stopped assist@assist-VirtualBox:~/Unix_Programming$
&
- 명령어 뒤에 &를 붙이면 background에서 작업을 수행함
assist@assist-VirtualBox:~/Unix_Programming$ ./bg & [2] 16871 Knock! assist@assist-VirtualBox:~/Unix_Programming$ Knock!
명령어 – jobs
jobs
- Background에서 실행되는 작업목록 (Job ID, 상태, 명령어)을 보여주는 명령어
assist@assist-VirtualBox:~/Untix_Programming$ jobs
[1]+ Stopped ./bg
[2]- Running ./bg &
- Job ID는 PID와는 별도로 부여되는 번호
- 작업목록은 현재 shell session에 딸린 것이며,
다른 session 과는 독립적이다.
job 명령어에는 다음과 같은 상태들이 있다
명령어 - bg
bg %(ID)
- Stopped 된 작업을 백그라운드에서 수행시킴
- 사용법 : bg %JobID
assist@assist-VirtualBox:~/Unix_Programming$ jobs
[1]+ Stopped ./bg
[2]- Running ./bg &
assist@assist-VirtualBox:~/Unix_Programming$ bg %1
[1]+ ./bg &
Knock!
assist@assist-VirtualBox:~/Unix_Programming$ Knock!
Knock!
Knock!
명령어 - fg
fg %(ID)
- Background에서 수행중인 작업을 Foreground로 옮김
- 사용법 : fg %JobID
assist@assist-VirtualBox:~/Unix_Programming$ fg %1
./bg
Knock!
jobs
Knock!
Knock!
명령어 – kill
kill
- 작업을 끝내거나, 프로세스를 종료시키는데 사용
- 사용법
kill %JobID : 수행중인 Job을 종료시킴
kill PID : 해당 프로세스 ID를 가진 프로세스를 종료
assist@assist-VirtualBox:~/Unix_Programming$ jobs
[2]+ Running ./bg &
assist@assist-VirtualBox:~/Unix_Programming$ kill %2
[2]+ Done ./bg
assist@assist-VirtualBox:~/Unix_Programming$ jobs
assist@assist-VirtualBox:~/Unix_Programming$
명령어 – kill -9
kill -9
-9 옵션은 강제종료(권장 X)
assist@assist-VirtualBox:~/Unix_Programming$ vi &
[1] 17614
assist@assist-VirtualBox:~/Unix_Programming$ jobs
[1]+ Stopped vi
assist@assist-VirtualBox:~/Unix_Programming$ kill -9 %1
[1]+ Killed vi
assist@assist-VirtualBox:~/Unix_Programming$ jobs
assist@assist-VirtualBox:~/Unix Programming$
'개발 · 컴퓨터공학' 카테고리의 다른 글
네트워크 프로그래밍 - 멀티프로세스 기반의 서버 구현 (0) | 2021.10.17 |
---|---|
UNIX - system call [exit, wait , waitpid], zombie process, orphan process (0) | 2021.10.16 |
UNIX - 파일 조작하기 (0) | 2021.10.14 |
네트워크 프로그래밍 - Error Control, Congestion control (0) | 2021.10.13 |
UNIX - compile 명령어 정리, Makefile (0) | 2021.10.12 |