'System Program/I/O'에 해당되는 글 7건

  1. 2014.03.13 고급 I/O 모델 : epoll() 함수
  2. 2014.03.12 고급 I/O 모델 : poll() 함수
  3. 2014.03.01 고급 I/O 모델 : select() 시스템 호출
  4. 2014.02.26 access() 함수
  5. 2014.02.26 stat() 관련 함수
  6. 2014.02.21 fcntl() 함수
  7. 2013.10.10 파일 I/O: 범용 I/O 모델

고급 I/O 모델 : epoll() 함수

System Program/I/O 2014. 3. 13. 11:08

1. epoll() 함수

 

epoll() 함수는 select()와 poll() 함수와 동일하게 I/O 멀티플렉싱으로 사용된다.

단 epoll() 함수는 리눅스에서만 호환성을 갖는 한계가 있다.

 

epoll() 함수는 기존 두 함수에 비해서 파일 디스크립터의 준비 상태를 알리는 방식에서

더 유연성을 갖는다. 

 

1.1. 상태 변화를 알리는 방식 

 

  • Level-Triggered Notification

- 상태 변화를 감지하고자 하는 파일 디스크립터가 준비되면 무조건 알리는 방식

 

  • Edge-Triggered Notification

- 항상 새로 준비된 파일 디스크립터에 대해서만 알리는 방식

 

두 알림 방식이 마음에 잘 왔다지 않을 것이다. 쉽게 구분하는 방법은 두 번째 방식은 일단 A라는

파일 디스크립터에 대해서 알림을 받았는데 다른 새로운 파일 디스크립터가 준비되기 전에

다시 같은 A가 알림을 받을 준비가 되면 생략한다. 하지만 첫번째는 중복과 상관없이 무조건 알린다.

 

1.2. 각 함수별로 알림 지원 여부

 

I/O 모델 

 Level-Triggered

 Edge-Triggered

 select(), poll()

 O

 X 

 시그널 기반 I/O

 X

 O 

 epoll()

 O

O

 

시그널 기반 I/O에 대한 설명은 생략한다. 개인적으로 그 다지 좋은 방법은 아닌 것 같아서 ...

 

2. epoll() API 함수들

 

2.1. epoll_create() 함수

 

#include <sys/epoll.h>

 

int epoll_create(int size);

 

성공하면 파일 디스크립터를 리턴하고, 에러가 발생하면 '-1'을 리턴

 

매개 변수 size에는 감시할 파일 디스크립터의 수를 명시한다.

성공하면 epoll_create()는 자신의 다른 함수에서 사용할 새로운 파일 디스크립터를 리턴한다.

물론 dup() 함수 같은 것으로 다른 파일 디스크립터처럼 복사하고 이용할 수 있다.

 

2.2. epoll_ctl() 함수 : 관심 목록 변경 및 알림 방식 변경

 

#include <sys/epoll.h>

 

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev);

 

성공하면 '0'을 리턴하고, 에러가 발생하면 '-1'을 리턴

 

[주의 사항] 디스크 파일 디스크립터는 대상에서 제외된다.

 

  • op 매개 변수

 

op 

설명 

 EPOLL_CTL_ADD

 관심있는 파일디스크립터를 추가

 EPOLL_CTL_MOD

 기존 파일 디스크립터를 수정

 EPOLL_CTL_DEL

 기존 파일 디스크립터를 관심 목록에서 삭제

 

  • epoll_event 구조체

 

struct epoll_event{

uint32_t    events;                                                /* epoll 이벤트 (비트 마스트) */

epoll_data_t    data;                                             /* 사용자 데이터 */

};

 

typedef union epoll_data {

void    *ptr;                                                        /* 사용자 정의 데이터 포인터 */

int    fd;                                                             /* 파일 디스크립터 */

uint32_t    u32;                                                    /* 32비트 정수 */

uint64_t    u64;                                                    /* 64비트 정수 */

} epoll_data_t;

 

2.3. epoll_wait() : 알림 기다림.

 

#include <sys/epoll.h>

 

int epoll_wait(int epfd, struct epoll_event *evlist, int maxevents, int timeout);

 

성공하면 준비된 파일 디스크립터 수 리턴, '0'은 타임아웃 경우, '-1'은 에러를 말한다.

 

준비된 파일 디스크립터를 배열로 리턴한다. maxevents는 리턴한 배열의 갯수이다.

timeout 값의 의미는 앞의 select(), poll()과 동일하므로 생략한다.

 

  • epoll events 필드 가능한 비트 마스크

 

비트 

입력 

리턴 

설명 

 EPOLLIN

 O

  O 

 높은 순위 데이터를 제외한 데이터를 읽을 수 있다.

 EPOLLPRI

 O

O

 높은 순위 데이터를 읽을 수 있다.

 EPOLLRDHUP

 O

 O 

 상대편 소켓 shutdown 확인

 EPOLLOUT

 O

 O 

 일반 데이터를 기록할 수 있다.

 EPOLLET

 O

 X 

 에지 트리거를 알림 방식으로 선택 (기본은 레벨트리거 임)

 EPOLLONESHOT

 O

 X 

 이벤트를 알린 후에 이벤트 감시를 비활성화

 EPOLLERR

 X

 에러가 발생함.

 EPOLLHUP

 X

 행업 발생

 

많은 면에서 poll() 함수의 이벤트와 유사하다.

 

3. 예제

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/epoll.h>

#define MAX_BUFFER_LEN 256
#define MAX_EVENT_NUM	1

int main(int argc, char *argv[])
{
	int retval, m_read, m_write;
	int i;
	int fd;
	int epfd;
	struct epoll_event ev;
	struct epoll_event evlist[MAX_EVENT_NUM];
	char buffer[MAX_BUFFER_LEN];
	
	if((fd = open("./temp.txt", O_RDWR)) == -1)
	{
		perror("open : ");
		exit(EXIT_FAILURE);
	}

	/* epoll create */
	epfd = epoll_create(1);
	if(epdf == -1)
	{
		perror("epoll_create : ");
		exit(EXIT_FAILURE);
	}	
	
	/* epoll control */
	ev.events = EPOLLIN;
	ev.data.fd = STDIN_FILENO;
	
	if(epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
	{
		perror("epoll_ctl : ");
		exit(EXIT_FAILURE);
	}	
	
	while(1)
	{
		memset(buffer, 0x00, MAX_BUFFER_LEN);
		retval = epoll_wait(epfd, evlist, MAX_EVENT_NUM, -1);
		if(retval == -1)
		{
			/* signal interrupt */
			if(errno == EINTR)
			{
				continue;
			}
			else
			{			
				perror("epoll_wait : ");
				exit(EXIT_FAILURE);			
			}	
		}
		
		printf("retval = %d \n", retval);

		for(i = 0; i < MAX_EVENT_NUM; i++)
		{
		
			if(evlist[i].events & EPOLLIN)
			{
				m_read = read(STDIN_FILENO, buffer, MAX_BUFFER_LEN);
				printf("[read] m_read = %d \n", m_read);
				
				m_write = write(fd, buffer, m_read);
				printf("[write] m_write = %d \n", m_write);
			}
		}
		
		usleep(1000);
	}

	close(fd);
	exit(EXIT_SUCCESS);
}


 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : poll() 함수  (0) 2014.03.12
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
:

고급 I/O 모델 : poll() 함수

System Program/I/O 2014. 3. 12. 20:44

1. poll() 시스템 함수

 

select()와 비슷한 작업을 수행한다. select() 함수가 BSD로부터 기원한다면 poll() 함수는 시스템 V로부터

기원한다. 두 함수간에 차이점으로는 파일디스크립터를 관리하는 방식면에서 서로 다르다.

 

#include <poll.h>

 

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

 

준비된 파일 디스크립터 수를 리턴한다.

타임 아웃일 경우 '0'을, 에러가 발생하면 '-1'을 리턴한다. 

 

pollfd 구조체는 아래와 같다. nfds는 pollfd 배열의 갯수를 의미한다.

 

struct pollfd {

int fd;                                                        /* 파일 디스크립터 */

short events;                                             /* 확인하기를 원하는 이벤트에 대한 비트마스크 */

short revents;                                            /* 리턴된 이벤트 마스크 */

}; 

 

1.1. timeout 값

 

 값

설명 

 -1

 pollfd 구조체에 포함된 파일 디스크립터 중 하나가 준비되거나 이벤트를 수신할 때까지

 블록한다. (블록의 정도는 파일디스크립터의 종류에 따라 다르다)

 0

 블록하지 않고 파일디스크립터가 준비 상태인지만을 확인한다.  

 0 보다 큰값

 최대 설정된 타임아웃 기간만큼 블록한다.  

 

 1.2. 리턴값

 

 값

설명 

 -1

 에러가 발생 

 0

 파일 디스크립터가 준비되기 전에 타임아웃된 경우

 양수

 준비된 파일 디스크립터의 갯수

 

2. events/revents에 대한 비트 마스크 값

 

 비트

events 

revents 

설명 

 POLLIN

 O

 O

 높은 우선순위 데이터 외의 데이터를 읽을 수 있다.

 POLLRDNORM

 O

 O

 상동 (리눅스는 POLLIN과 동일하게 동작)

 POLLRDBAND

 O

 O

 우선순위 데이터를 읽을 수 있다. (리눅스 사용 안함)

 POLLPRI

 O

 O

 높은 우선순위 데이터를 읽을 수 있다.

 POLLRDHUP

 O

 O

 상대편 소켓 셧다운

 POLLOUT

 O

 O

 일반 데이터를 기록할 수 있다.

 POLLWRNORM

 O

 O

 상동 (리눅스는 POLLOUT과 동일하게 동작)

 POLLWRBAND

 O

 O

 우선순위 데이터를 기록할 수 있다.

 POLLERR

 X

 O

 에러가 발생했다.

 POLLHUP

 X

 O

 장애가 발생했다.

 POLLNVAL

 X

 O

 파일 디스크립터가 열리지 않는다.

 POLLMSG

 X

 X

 리눅스에서는 사용하지 않음.

 

3. 파일 디스크립터의 준비 상태

 

select()와 poll() 함수는 모든 파일 디스크립터 종류에서 블록되지는 않는다. 파일 디스크립터의 종류마다

블록의 동작이 다르다. 예로 일반 파일에 대한 파일 디스크립터는 블록하지 않고 바로 리턴한다.

이 예제가 select() 함수편의 예제에서 select() 함수의 리턴값을 찍어보면 알 수 있다.

따라서 I/O 멀티플렉싱 기법을 사용 시에는 파일 디스크립터의 종류에 대한 블록 동작에 대해서 잘 살펴봐야 한다.

 

4. 예제

 

select() 함수 예제 편에서 디스크 파일 디스크립터를 대상으로 했다면, 여기서는 표준 입력을 블록 대상으로 하였다.

select() 함수 편에서 retval값을 보면 실제 블록되지 않는다. 항상 준비된 상태가 된다.

파일 디스크립터 종류에 따른 블록되는 현상 차이를 보기위해서 poll() 예제에서는 표준 입력을 대상으로 예제를

작성하였다. 두 예제 간의 차이점을 보는 것도 도움이 될 것이다.  

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <poll.h>

#define MAX_BUFFER_LEN 256

int main(int argc, char *argv[])
{
	int retval, m_read, m_write;
	int fd;
	struct pollfd pollfds[1];
	char buffer[MAX_BUFFER_LEN];
	
	if((fd = open("./temp.txt", O_RDWR)) == -1)
	{
		perror("open : ");
		exit(EXIT_FAILURE);
	}

	pollfds[0].fd = STDIN_FILENO;
	pollfds[0].events = POLLIN;
	
	while(1)
	{
		memset(buffer, 0x00, MAX_BUFFER_LEN);
		retval = poll(pollfds, 1, -1);
		if(retval == -1)
		{
			perror("poll : ");
			exit(EXIT_FAILURE);			
		}
		
		printf("retval = %d \n", retval);
		
		if(pollfds[0].revents & POLLIN)
		{
			m_read = read(STDIN_FILENO, buffer, MAX_BUFFER_LEN);
			printf("[read] m_read = %d \n", m_read);
			
			m_write = write(fd, buffer, m_read);
			printf("[write] m_write = %d \n", m_write);
		}
		
		usleep(1000);
	}

	close(fd);
	exit(EXIT_SUCCESS);
}

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : epoll() 함수  (0) 2014.03.13
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
:

고급 I/O 모델 : select() 시스템 호출

System Program/I/O 2014. 3. 1. 15:47

1. select() 시스템 호출

 

I/O 멀티플렉싱을 구현한 시스템 함수 중에 하나로 I/O Operation이 가능한 파일 디스크립터를 감시할 수 있다.

 

#include <sys/time.h>

#include <sys/select.h>

 

 int select(int nfds, fd_set *readfds, fd_set *writefds,

  fd_set *exceptfds, struct timeval *timeout);

 

준비된 파일 디스크립터 수를 리턴한다.

타임 아웃일 경우 '0'을, 에러가 발생하면 '-1'을 리턴한다. 

 

  • timeout 필드 설정에 따른 동작성

 

 timeout

설명 

 0

 select()함수는 블록되지 않고 지정된 파일 대기 상태인지만 확인하고 즉시 리턴한다.

 NULL

 읽기/쓰기/예외에 지정한 파일 디스크립터 중에 하나 이상 준비된 상태일 때 리턴

 '0' 이 아닌 값

 지정된 시간만큼 기다린다

 

  • 리턴값 상세

 

 리턴값

설명 

 -1

 에러가 발생한 경우이고, EBADF와 EINTR 에러로 에러가 설정될 수 있다.

 EBADF는 세개의 파일 디스크립터 집합에 유효하지 않는 파일 디스크립터가 설정된 경우

 EINTR은 시그널 핸들러에 의해서 발생한 것으로 EINTR은 자동으로 재시작되지 않는다.  

 0

 파일 디스크립터가 준비상태가 되기 전에 타임아웃된 경우

 양수

 한개 이상의 파일 디스크립터가 준비된 경우 

   

2. fd_set 데이터형 처리 함수들

 

위의 select() 함수 정의 부분에서 각각 읽기, 쓰기, 예외 파일 디스크립터 집합에 대한 기본 자료형

fd_set에 대한 자료형을 처리하기 위한 함수를 소개한다.

 

#include <sys/select.h>

void FD_ZERO(fd_set *fdset);

void FD_SET(int fd, fd_set *fdset);

void FD_CLR(int fd, fd_set *fdset);

 

int FD_ISSET(int fd, fd_set *fdset);

fd 가 fdset에 포함되어 있으면 '1'을 아니면 '0'을 리턴한다.  

 

위의 함수들에 대한 자세한 설명을 스킵한다. 이름에서 그냥 유추할 수 있다.

 

파일 디스크립터 집합의 최대 크기는 FD_SETSIZE 상수에 정의되어 있다. 리눅스에서는 1024이다.

 

3. 예제

 

temp.txt 파일을 읽기 전용으로 하나 열고, 여기에 데이터가 쓰여지면 select() 함수의 블록이

풀리고 표준출력에 파일에 입력된 내용을 출력한다. 간단한 예제를 통해서 함수 사용법을 익히는데 중점을 둔다.

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/select.h>

#define MAX_BUFFER_LEN 256

int main(int argc, char *argv[])
{
	int retval, n;
	int fd;
	fd_set readfds, writefd;
	char buffer[MAX_BUFFER_LEN];
	
	if((fd = open("./temp.txt", O_RDONLY)) == -1)
	{
		perror("open : ");
		exit(EXIT_FAILURE);
	}

/*	
	newfd = dup(STDOUT_FILENO);
	if(newfd == -1)
	{
		perror("dup : ");
		exit(EXIT_FAILURE);	
	}
	
	close(STDOUT_FILENO);
*/	
	while(1)
	{
		FD_ZERO(&readfds);
		FD_ZERO(&writefd);
		FD_SET(fd, &readfds);
		
		retval = select(fd + 1, &readfds, &writefd, NULL, NULL);

		switch(retval)
		{
			case -1:
				perror("slect : ");
				exit(EXIT_FAILURE);
			
			default :
				if(FD_ISSET(fd, &readfds))
				{
					while((n = read(fd, buffer, MAX_BUFFER_LEN)) > 0)
					{
						printf("%s", buffer);
					}
				}
				
				memset(buffer, 0, MAX_BUFFER_LEN);
				break;
		}
		
		usleep(1000);
	}
	
	close(fd);
	exit(EXIT_SUCCESS);
}

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : epoll() 함수  (0) 2014.03.13
고급 I/O 모델 : poll() 함수  (0) 2014.03.12
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
:

access() 함수

System Program/I/O 2014. 2. 26. 16:10

1. 정의

 

프로세스의 실제 사용자와 그룹 ID에 기반하여 파일 접근권을 검사한다.

 

#include <unistd.h>

 int access(const char *pathname, int mode);

모든 권한이 혀용된 경우 '0'을 리턴하고, 에러가 발생하면 '-1'을 리턴 

 

pathname이 심볼릭 링크이면 역참조한다.

 

위 함수의 mode에 할당될 수 있는 매크로는 아래와 같고, OR연산으로 여러개 지정할 수 있다.

 

 상수

설명 

 F_OK

 파일이 존재하는가? 

 R_OK

 파일을 읽을 수 있는가?

 W_OK

 파일에 쓸 수 있는가?

 X_OK

 파일이 실행될 수 있는가?

 

 

 

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : poll() 함수  (0) 2014.03.12
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
파일 I/O: 범용 I/O 모델  (0) 2013.10.10
:

stat() 관련 함수

System Program/I/O 2014. 2. 26. 13:25

1. 시스템 함수들

 

stat(), lstat(), fstat() 시스템 함수들을 정리한다.

이 함수들은 파일에 대한 유용한 정보를 추출해 준다.

 

2. 정의들

 

#include <sys/stat.h>

int stat(const char *pathname, struct stat *statbuf);

int lstat(const char *pathname, struct stat *statbuf);

int fstat(int fd, struct stat *statbuf);

성공하면 '0'을 리턴하고, 에러가 발생하면 '-1'을 리턴 

 

위의 함수는 아래의 구조체를 통해서 정보를 리턴한다.

기본 구조는 stat()에서 출발하고 lstat() 함수는 파일이 심볼릭 링크인 경우를 

fstat() 함수는 파일 경로 정보 대신 열린파일 디스크립터를 입력으로 받는 차이점이 있다.  

 

struct stat{
    dev_t          st_dev;          /* 파일이 위치한 디바이스 ID */
    ino_t           st_ino;          /* 파일의  i-노드 수 */
    mode_t        st_mode;       /* 파일 형식과 권한 */
    nlink_t         st_nlink;         /* 파일의 (하드)링크 수 */
    uid_t           st_uid;          /* 파일 소유자의 사용자 ID */
    gid_t           st_gid;          /* 파일 소유자의 그룹 ID */
    dev_t          st_rdev;         /* 파일 디바이스 특정 파일의 ID */
    off_t            st_size;         /* 파일의 전체 크기 (BYTE) */
    blksize_t     st_blksize;     /* I/O의 최적 블록크기 (바이트) */
    blkcnt_t       st_blocks;     /* 할당된 블록의 수(512B) */
    time_t          st_atime;       /* 마지막 파일 접근 시간 */
    time_t          st_mtime;       /* 마지막 파일 수정 시간 */
    time_t          st_ctime;       /* 마지막 상태 변경 시간 */
};

 

 

3. struct stat 구조체로부터 정보 추출

 

3.1. dev_t st_dev 정보

    디바이스의 major/minor가 합쳐져 있는 구조로 major()/minor()함수를 통해서 각각 원하는 값을 추출할 수 있다.

 

3.2. mode_t st_mode 정보 (가장 복잡하다)

    st_mode와 아래 매크로와 AND 연산을 수행하여 추출한다.

 

[파일 종류 검사 매크로] 

 

상수

테스트 매크로

설명

S_IFREG

S_ISREG()

일반파일 검사

S_IFDIR

S_ISDIR()

디렉토리 검사

S_IFCHR

S_ISCHR()

문자 디바이스 검사

S_IFBLK

S_ISBLK()

블록 디바이스 검사

S_IFIFO

S_ISFIFO()

FIFO나 파이프 검사

S_IFSOCK

S_ISSOCK()

소켓 검사

S_IFLNK

S_ISLNK()

심볼릭 링크 파일 검사

 

[파일 권한 비트 검사] {set-user-ID,set_group-ID.Sticky}/소유자/그룹/기타

 

 상수

8진수 

권한비트 

 S_ISUID

04000 

 set-user-ID

 S_ISGID

 02000

 set-group-ID

 S_ISVTX

 01000

 스티키

 S_IRUSR

 0400

 사용자-읽기

 S_IWUSR

 0200

 사용자-쓰기

 S_IXUSR

 0100

 사용자-실행

 S_IRGRP

 040

 그룹-읽기

 S_IWGRP

 020

 그룹-쓰기

 S_IXGRP

 010

 그룹-실행

 S_IROTH

 04

 기타-읽기

 S_IWOTH

 02

 기타-쓰기

 S_IXOTH

 01

 기타-실행

 

추가적으로 사용자/그룹/기타 각각에 대해서 모든 권한이 설정되었는지 여부를 검사하는 아래 매크로도 있다.  

 

S_IRWXU(0700), S_IRWXG(070), S_IRWXO(07)

 

 

4. 예제

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

int main(int argc, char *argv[])
{
	time_t t;
	struct stat statbuf;

	if(stat("./main.c", &statbuf) == -1)
	{
		perror("fopen");
		exit(EXIT_FAILURE);	
	}
	
	// major/minor number print
	printf("major = %ld\n", major(statbuf.st_dev));
	printf("minor = %ld\n", minor(statbuf.st_dev));
	
	// file total size print
	printf("file size = %ld \n", statbuf.st_size);
	
	// file modify time print
	t = statbuf.st_mtime;
	printf("%s\n", ctime(&t));

	// file mode check, the macro is defined to <sys/stat.h>
	//if((statbuf.st_mode & S_IFMT) == S_IFREG)
	if(S_ISREG(statbuf.st_mode))
		printf("regular file\n");
	
	exit(EXIT_SUCCESS);
}

 


 

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : poll() 함수  (0) 2014.03.12
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
access() 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
파일 I/O: 범용 I/O 모델  (0) 2013.10.10
:

fcntl() 함수

System Program/I/O 2014. 2. 21. 10:34

1. Usage

 

fcntl() 시스템 호출은 열린 파일 상태 플래그 변경, 파일 디스크립터 복제 및 접근 모드 제어등 다양한 기능을 수행한다.  

 

2. 함수 정의

 

#include <fcntl.h>

int fcntl(int fd, int cmd, ...);

 

                                                                           성공할 경우 리턴값은 cmd에 따라 다르다. 에러는 '-1'을 리턴 

 

3. 열린 파일 상태 검사 예시

 

int flags;
	
flags = fcntl(fd, F_GETFL);
if(flags == -1)
	perror("fcntl");
	
if(flags & O_SYNC)
	printf("writes are synchronized\n");


동기화된 쓰기용으로 파일이 열린 것인지를 검사한다. flags을 얻어오기 위해서 "F_GETFL"을 사용한다.

 

4. 접근 모드 상태 검사 예시

 

accessMode = flags & O_ACCMODE;

if(accessMode == O_WRONLY || accessMode == O_RDWR)
	printf("file is writable\n");


접근 모드을 검사하는 것은 별도의 추가적으로 O_ACCMODE라는 flag에 대해서 비트 연산을 수행해야 한다.

 

5. 일반적인 사용 예시

 

int flags;

flags = fcntl(fd, F_GETFL);
if(flags == -1)
	perror("fcntl");

flags |= O_APPEND;
if(fcntl(fd, F_SETFL, flags) == -1)
	perror("fcntl");


O_APPEND 상태 플래그를 추가하고자 할 경우, 기존에 값을 열어서 추가적으로 설정하는 것이 일반적인 방법이다.

설정 시에는 "F_SETFL"을 사용한다.

 

 

 

 

 

 

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : poll() 함수  (0) 2014.03.12
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
파일 I/O: 범용 I/O 모델  (0) 2013.10.10
:

파일 I/O: 범용 I/O 모델

System Program/I/O 2013. 10. 10. 07:28

1. 입출력 관련 시스템 호출

 

I/O를 수행하는 모든 시스템 호출은 파일 디스크립터라는 음이 아닌 정수를 통해 열려 있는 파일을 참조한다.

파일 디스크립터는 파이프, FIFO, 소켓, 터미널, 디바이스, 일반 파일 등 종류에 상관없이 모든 열려 있는 파일을 참조한다.

유닉스/리눅스의 I/O처리 철학이 모든 입출력 장치를 파일로 관주하는 맥락과 일치한다.

 

2. 표준 파일 디스트립터

 

 파일 디스트립터

 목적

POSIX 이름 

STDIO STREAM 

 0

 표준 입력

 STDIN_FILENO

 stdin

 1

 표준 출력

 STDOUT_FILENO

 stdout

 2

 표준 에러

 STDERR_FILENO

 stderr

 

위의 세 디스트립터는 항상 열려 있는데, 이유는 쉘을 통해 실행되는 프로그램은 쉘로부터 항상 열려있는 세개의 디스트립터를 상속받기 때문이다. 이 개념은 매우 중요하다. 네트워크나 이와 유사한 프로그램에서 dup()함수를 통해서 열려 있는 소켓의 디스크립터의 번호를 재 정의할 때 이 개념이 정립되어 있어야지 이해할 수 있다.

또한 프로그램에서 파일 디스트립터의 숫자를 통해서 파일을 처리할 수 있으나, 가능하면 <unistd.h>에 정의된 POSIX 표준 이름을 쓰는 편이 좋다.

 

2.1. 파일 열기: open()

 

#incldue <sys/stat.h>

#include <fcntl.h>

int open(const char *pathname, int flags, ... /* mode_t mode */);

                                                   성공하면 파일 디스크립터를 리턴하고, 에러가 발생하면 -1을 리턴한다.

 

open()함수가 리턴하는 파일 디스크립터는 항상 프로세스에서 사용하지 않는 가장 작은 수를 리턴한다. 따라서 기본적으로 앞에서 설명했듯이 0 ~ 2는 사용하고 있으므로 상식적으로 3부터 차례로 리턴될 것이다.

이런 동작 방식에 대한 이해를 하는 것이 매우 중요하다.

 

open()함수에서 사용하는 flags에 대해서 아래와 같이 정리할 수 있다.

 

 플래그

목적 

표준 

 O_RDONLY

 읽기 전용으로 연다

 v3

 OWRONLY

 쓰기 전용으로 연다

 v3

 O_RDWR

 읽고 쓰기용으로 연다

 v3

 O_CLOEXEC

 실행 시 닫기 플래그를 설정한다

 v4

 O_CREAT

 파일이 이미 존재하면 새로 만든다

 v3

 O_DIRECT

 파일 I/O가 버퍼 캐시를 우회한다

 

 O_DIRECTORY

 pathname이 디렉토리가 아니면 실패한다

 v4

 O_EXCL

 O_CREAT와 함께, 배타적으로 파일을 만든다

 v3

O_LARGEFILE

32비트 시스템에서 큰 파일을 열 때 쓴다

 

O_NOATIME

read()시에 파일 최종 접근 시간을 갱신하지 않는다

 

O_NOCTTY

pathname으로 제어 터미널이 되지 않게 한다

v3

O_NOFOLLOW

심볼링크를 역참조하지 않는다

v4

O_TRUNC

기존 파일의 길이를 0으로 설정한다

v3

O_APPEND

언제나 파일 끝에 추가해서 쓴다

v3

O_ASYNC

I/O가 가능해지면 시그널을 보낸다

 

O_DSYNC

동기 I/O 데이터 무결성을 제공한다

리눅스 : 2.6.33부터

O_NONBLOCK

비블로킹 모드로 연다

v3

O_SYNC

파일 쓰기를 동기 모드로 설정한다

v3

 

■ open() error 값

 

에러가 발생하면 '-1'을 리턴하고, errno를 보면 에러의 원인을 알 수 있다. 발생 가능한 에러에 대해서 살펴본다.

 

 EACCES

호출하는 프로세스가 flags에 지정한 모드로 파일에 접근할 수 없다 

 EISDIR

지정된 파일이 디렉토리이고, 호출자가 쓰기용으로 열려고 했다

 EMFILE

파일디스크립터의 개수가 프로세스의 한도를 넘었다

 ENFILE

열린 파일의 개수가 시스템 전체 한도에 도달했다 

 ENOENT

지정된 파일이 존재하지 않고, O_CREAT가 지정되지 않았거나, 지정되었더라도 pathname으로 지정된 경로명이 존재하지 않는다

 EROFS

파일이 읽기전용인데 호출자 쓰기용으로 열려고 했다

 ETXBSY

지정된 파일이 실행 중에 있다.  

 

2.2. create() 시스템 호출

 

#include <fcntl.h>

int create(const char *pathname, mode_t mode );

                                                   성공하면 파일 디스크립터를 리턴하고, 에러가 발생하면 -1을 리턴한다.

 

open()과 동일한 기능이지만 현재는 사용되지 않는다.

 

2.3. read() 시스템 호출

 

#include <unistd.h>

ssize_t read(int fd, void *buffer, size_t count);

                                                   읽은 바이트 수를 리턴한다. EOF인 경우에는 0을 에러가 발생하면 -1을 리턴

 

위의 함수에서 size_t count는 매개변수는 읽을 최대 바이트 수를 지정한다.

 

2.4. write() 시스템 호출

 

#include <unistd.h>

ssize_t write(int fd, void *buffer, size_t count);

                                                   쓴 바이트 수를 리턴한다. 에러가 발생하면 -1을 리턴

 

디스크에서 I/O를 수행할 때 write()가 성공하였다고해서 데이터가 디스크로 전송되었다고 보증할 수는 없다. 커널의 디스크 I/O 동작에 대해서 버퍼링을 수행하기 때문이다. 자세한 내용은 차 후에 보도록 한다.

 

2.5. close() 시스템 호출

 

#include <unistd.h>

int close(int fd);

                                                   성공하면 0을 에러가 발생하면 -1을 리턴

 

2.6. lseek() 시스템 호출

 

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

                                                   성공하면 새로운 파일 오프셋을 리턴하고, 에러가 발생하면 -1을 리턴

 

위에서 offset은 바이트 단위로 설정하여 파일 시작에서 몇 바이트 떨어져 있는 지점을 지정하기 위해서 사용된다.

뒤의 whence는 아래와 같은 의미를 갖는다. 이 함수는 모든 종류의 디바이스에 적용할 수 있는 것은 아니다. 일반적으로

파일에 적용될 수 있다고 보면 된다.

 

  • SEEK_SET : 파일 오프셋 계산의 기준점이 파일의 시작점으로 설정 
  • SEEK_CUR : 파일 오프셋의 기준점을 현재 파일 오프셋으로 설정
  • SEEK_END : 파일 오프셋의 기준점을 파일 끝으로 설정

 

2.7. ioctl() 시스템 호출

 

#include <sys/ioctl.h>

int ioctl(int fd, int request, ... /*argp */);

                                                   성공하면 request에 따라 다르다, 에러가 발생하면 -1을 리턴

 

위의 사용은 일반적으로 디바이스 드라이버 응용에서 많이 사용하는 방식이다. 커널쪽에 ioctl의 request에 대응하는 코드가 별도로 구현되야 한다.

즉 위의 함수는 앞서 설명한 범용 I/O 모델에서 벗어나는 파일과 디바이스 오퍼레이션을 위한 범용 메카리즘이다.  

 

3. 기타

 

커널 2.6.22부터는 /proc/PID/fdinfo 디렉토리에서 각 프로세스에 대한 파일 디스크립터 정보를 얻을 수 있다.

자세한 내용은 참고서적 144Page 참조

 

 

 

 

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : poll() 함수  (0) 2014.03.12
고급 I/O 모델 : select() 시스템 호출  (0) 2014.03.01
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
: