2. 아래와 같이 File operation만 치환하려고 했는데,
i_fop가 const로 정의되어 있어서 (linux/fs.h ln642) 에러만 난다.
code) filp->f_dentry->d_inode->i_fop->llseek = my_llseek;
3. 결국 Block device driver 형태로 만드는 수 밖에 없는데,
시간을 더 쓸 수가 없어서 이쯤에서 pending. 다음 기회에.
커널 다운로드 (아래의 작업들 부터는 루트 권한으로 진행합시다.)
커널 컴파일
주위에 도움이 되길 바라며...
프로그램에 두 줄의 함수 호출만 추가하여
std i/o를 redirection하는 함수를 만들려다..
결국 만들었습니다!!
아..재밌는데 더 하긴 귀찮네요.
// redirection_in.cc
// redirection in을 간단히 사용하기 위한 함수를 정의
// 키보드 입력을 파일로 대체!
#include <fcntl.h>
#include <sys/io.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
int redirect_original_stdin;
int redirect_stdin_to_file( char * fname )
{
// stdin을 keyboard에서 read pipe로 대체하는 함수
// 1. pipe 초기화
// 2. fork로 자식 프로세스 생성
// 부모 - stdin(키보드)을 복제, stdin을 read pipe로 대체, read pipe 닫기, 0을 리턴
// 여기서부턴 자식 프로세스만
// 3. 파일 오픈
// 4. 파일 내용을 write pipe에 기록
// 5. 파일 닫고
// 6. write pipe 닫고
// 7. 종료(return 말고 exit)
int pid, result;
int redirect_fdpipe[2];
if( pipe(redirect_fdpipe) == -1 )
return 0;
pid = fork();
if( pid>0 )
{
close( redirect_fdpipe[1] );
redirect_original_stdin = dup( STDIN_FILENO );
dup2( redirect_fdpipe[0], STDIN_FILENO );
close( redirect_fdpipe[0] );
return 0;
}
else if( pid==0 )
{
// 이 자식 프로세스가 입력 파일을 읽어서
// 부모 프로세스의 stdin에게 전달한다.
int n,i;
const int BUFFSIZE = 100;
char buf[BUFFSIZE];
close( redirect_fdpipe[0] );
FILE * file;
file = fopen( fname, "r" );
if( file==NULL )
exit(0);
i = 0;
while( (n=fread(buf,1,BUFFSIZE,file))>=0 )
{
if( n>0 )
{
write( redirect_fdpipe[1], buf, n );
i = 0;
}
else
{
if( ++i>10 )
break;
}
}
close( redirect_fdpipe[1] );
exit(0);
}
}
int redirect_stdin_restore()
{
// stdin을 read pipe에서 keybooard로 복구하는 함수
// 1. 버퍼에 있는 데이터들 전부 처리(fflush)
// 2. stdin (파이프) 닫기
// 3. 백업한 stdin의 descriptor을 이용해 stdin을 키보드로 복구(dup2)
int result;
fflush( stdin ); // 이거없음 곤란한 경우 가끔 발생
result = close( STDIN_FILENO );
if( result<0 )
return -1;
result = dup2( redirect_original_stdin, STDIN_FILENO );
if( result<0 )
return -1;
return 0;
}
int main(int argc, char **argv)
{
int result;
// 예제 1
// file을 stdin 입력으로-
result = redirect_stdin_to_file( "input.dat" );
if( result<0 )
{
printf("redirect_stdin_to_file error\n");
return 0;
}
// 아래 fork는 redirection이 아니라 서브 프로그램을 실행하기 위한 절차
int pid = fork();
if( pid==0 )
{
execl( "./sinout", "/sinout", NULL );
exit(0);
}
else if( pid>0 )
{
int status;
wait( &status );
}
else
{
// error!
}
result = redirect_stdin_restore();
if( result<0 )
{
printf("redirect_stdin_restore error\n");
return 0;
}
return 0;
}
프로그램에 두 줄의 함수 호출만 추가하여
std i/o를 redirection하는 함수를 만들려다..
결국 만들었습니다!!
아..재밌는데 더 하긴 귀찮네요.
// redirection_out.cc
// redirection out을 간단히 사용하기 위한 함수를 정의
#include <fcntl.h>
#include <sys/io.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
int redirect_original_stdout;
FILE * redirect_stream;
int redirect_stdout_to_file( char * fname, int append=0 )
{
// stdout을 screen에서 file로 대체하는 함수
// 1. 파일 열기(open)
// 2. stdout의 descriptor 백업(dup)
// 3. stdout을 file로 대체(dup2)
// 4. 파일 닫기(close)
int result;
char openflag[5];
if( append )
strcpy( openflag, "a" );
else
strcpy( openflag, "w+" );
redirect_stream = fopen( fname, openflag );
if( redirect_stream==NULL )
return -1;
if( append )
fseek( redirect_stream, 0, SEEK_END );
redirect_original_stdout = dup( STDOUT_FILENO );
if( redirect_original_stdout<0 )
return -1;
result = dup2( fileno( redirect_stream ), STDOUT_FILENO );
if( result<0 )
return -1;
result = fclose( redirect_stream );
if( result!=0 )
return -1;
return 0;
}
int redirect_stdout_restore()
{
// stdout을 file에서 screen으로 복구하는 함수
// 1. 버퍼에 있는 데이터들 모두 처리(fflush)
// 2. stdout (파일) 닫기
// 3. 백업한 stdout의 descriptor을 이용해 stdout을 화면으로 복구(dup2)
int result;
fflush( stdout ); // 이거없음 곤란한 경우 가끔 발생
result = close( STDOUT_FILENO );
if( result<0 )
return -1;
result = dup2( redirect_original_stdout, STDOUT_FILENO );
if( result<0 )
return -1;
return 0;
}
int main(int argc, char **argv)
{
int result;
int appendmode;
if( argc==2 && atoi(argv[1])==1 )
appendmode = 1;
else
appendmode = 0;
// 예제 1
// stdout으로의 출력을 file로-
result = redirect_stdout_to_file( "output.txt", appendmode );
if( result<0 )
{
printf("redirect_stdout_to_file error\n");
return 0;
}
// 파일에 쓰기 1
printf( "this is file output 1 (buffered)\n" );
// 파일에 쓰기 2
char * msg = "this is file output 2 (direct)\n";
write( STDOUT_FILENO, msg, strlen(msg) );
result = redirect_stdout_restore();
if( result<0 )
{
printf("redirect_stdout_restore error\n");
return 0;
}
return 0;
}
문득 궁금해져서...새벽에 삽질했습니다.
부모 프로세스가 stdin또는 stdout을 다른 I/O로 redirection 했다면,
fork로 만든 자식 프로세스나 exec로 실행한 서브 프로그램도
stdin, stdout을 redirection한 I/O를 유지하고 있을까?
-> yes!
// dupout.cc
// 자식/서브 프로세스가 부모 프로세스의 stdin/stdout의 특성을 물려받는지 알아보기 위한 테스트
#include <fcntl.h>
#include <io.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
//int fd = open("flist.cc", O_RDONLY);
int fd = open( "a.txt", _O_CREAT|_O_RDWR|_O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO );
if( fd<=0 )
{
char * errmsg = "Cannot created file\n";
write( STDOUT_FILENO, errmsg, strlen(errmsg) );
return 0;
}
// 예제 1
// STDOUT_FILENO의 입력을 File로
// STDOUT_FILENO으로의 입력을 fd로 redirection
int tempFd = dup(STDOUT_FILENO);
dup2( fd, STDOUT_FILENO );
// STDOUT_FILENO에 기록 - fd에 기록된다
char * msg1 = "this is file output\n";
write( STDOUT_FILENO, msg1, strlen(msg1) );
// 자식 프로세스 생성
// fork로 생성한 자식 프로세스가 부모 프로세스의 stdin/stdout 성질을 물려받는가?
int pid = fork();
if( pid>0 )
{
// parent
int stat=0;
wait(&stat);
}
else if( pid==0 )
{
// child
char * msgch = "this is message from the child\n";
write( STDOUT_FILENO, msgch, strlen(msgch) );
// 한번 더 자식 프로세스 생성, 증손이네ㅋㅋ
// execl로 실행한 서브 프로세스가 부모 프로세스의 stdin/stdout 성질을 물려받는가?
int pid = fork();
if( pid==0 )
// Child
execl( "/bin/ls", "/bin/ls", NULL );
return 0;
}
else
{
// error
}
close( fd );
// STDOUT_FILENO 복구
dup2( tempFd, STDOUT_FILENO );
close( tempFd );
// STDOUT_FILENO에 기록 - 화면에 출력된다
char * msg2 = "this is screen output\n";
write( STDOUT_FILENO, msg2, strlen(msg2) );
return 0;
}