1. 파일 설명자 가 커 널 에서 데이터 구조 dup / dup 2 를 구체 적 으로 말 하기 전에 파일 설명자 가 커 널 에 있 는 형 태 를 먼저 알 아 볼 필요 가 있다 고 생각 합 니 다.하나의 프로 세 스 가 존재 하 는 동안 일부 파일 이 열 려 서 일부 파일 설명 자 를 되 돌려 줍 니 다. 셸 에서 프로 세 스 를 실행 합 니 다. 기본 값 은 3 개의 파일 설명자 가 존재 합 니 다 (0, 1, 2). 0 은 프로 세 스 의 표준 입력 과 연결 되 고 1 은 프로 세 스 의 표준 출력 과 연결 되 며 2 는 프로 세 스 의 표준 오류 출력 과 연 결 됩 니 다.프로 세 스 가 현재 열 려 있 는 파일 설명 자 는 / proc / 프로 세 스 ID / fd 디 렉 터 리 를 통 해 볼 수 있 습 니 다.다음 그림 에서 문 제 를 명확 하 게 설명 할 수 있 습 니 다: 프로 세 스 표 항목 - - - - - fd 로고 파일 포인터 _____________________ fd 0:|________|____________|------------> 파일 테이블 fd 1: | | |fd 2:|________|____________| fd 3:|________|____________| | ....... | |_____________________| 그림 1 파일 시트 에는 파일 상태 표지, 현재 파일 오프셋, v 노드 포인터 가 포함 되 어 있 습 니 다. 이것 은 본 논문 에서 토론 하 는 중점 이 아 닙 니 다. 우 리 는 모든 열 린 파일 설명자 (fd 표지) 가 프로 세 스 표 에 자신의 파일 표 항목 이 있 고 파일 포인터 가 가리 키 는 것 만 알 아야 합 니 다. 2. dup / dup 2 함수 APUE 와 man 문 서 는 두 함수 의 역할 을 한 마디 로 간단명료 하 게 말 합 니 다. 기 존 파일 설명 자 를 복사 합 니 다. \ #include int dup(int oldfd); int dup2(int oldfd, int newfd); 그림 1 에서 이 과정 을 분석 합 니 다. dup 함 수 를 호출 할 때 커 널 은 프로 세 스 에서 새로운 파일 설명 자 를 만 듭 니 다. 이 설명 자 는 현재 사용 가능 한 파일 설명자 의 최소 수치 입 니 다. 이 파일 설명 자 는 oldfd 가 가지 고 있 는 파일 표 항목 을 가리 키 고 있 습 니 다.프로 세 스 표 항목 - - - - fd 로고 파일 포인터 _____________________ fd 0:|________|____________| ______ fd 1:|________|____________|----------------> | | fd 2:|________|____________| |파일 테이블 | fd 3: | | ....... | |_____________________| 그림 2: dup 를 호출 한 설명도 그림 2 와 같이 oldfd 의 값 이 1 이면 현재 파일 설명자 의 최소 값 이 3 이면 새 설명자 3 은 설명자 1 이 가지 고 있 는 파일 표 항목 을 가리킨다.dup 2 와 dup 의 차 이 는 new fd 매개 변수 로 새 설명자 의 수 치 를 지정 할 수 있 습 니 다. new fd 가 열 렸 다 면 먼저 닫 습 니 다.new fd 가 oldfd 와 같다 면, dup 2 는 new fd 로 돌아 가 닫 지 않 습 니 다.dup 2 함수 가 되 돌아 오 는 새 파일 설명 자 는 인자 oldfd 와 같은 파일 표 항목 을 공유 합 니 다.APUE 는 다른 방법 으로 이 문 제 를 설명 했다. 실제로 dup (oldfd) 를 호출 했다.등가 fcntl (oldfd, F DUPFD, 0) 에서 dup 2 (oldfd, newfd) 를 호출 합 니 다.등가 close(oldfd); fcntl(oldfd, F_DUPFD, newfd); 3. CGI 에서 dup 2 가 CGI 프로그램 을 쓴 사람 은 잘 알 고 있 습 니 다. 브 라 우 저 에서 post 방법 으로 폼 데 이 터 를 제출 할 때 CGI 가 읽 는 데 이 터 는 표준 입력 stdin 이 고 데 이 터 는 표준 출력 stdout (c 언어 는 printf 함수 이용) 입 니 다.우리 의 정상 적 인 이해 에 따 르 면 printf 의 출력 은 터미널 에 표시 되 어야 합 니 다. 원래 CGI 프로그램 은 dup 2 함 수 를 사용 하여 STDOUT 를FINLeno (이 매크로 는 untstd. h 에서 정의 되 고 1) 이 파일 설명 자 는 연결 소켓 으로 바 뀌 었 습 니 다.dup2(connfd, STDOUT_FILENO);/ * 실제 상황 은 파이프 와 도 관련 되 어 있 습 니 다. 본 고의 중점 이 아 닙 니 다. * / 첫 번 째 절 에서 말 한 바 와 같이 프로 세 스 의 기본 파일 설명자 1 (STDOUT FILENO) 은 표준 출력 stdout 과 관련 되 어 있 습 니 다. 커 널 에 있어 서 모든 열 린 파일 은 파일 설명자 로 참조 되 고 커 널 은 흐름 의 존 재 를 모 릅 니 다 (예 를 들 어 stdin, stdout).그래서 printf 함수 가 stdout 에 출력 한 데 이 터 는 마지막 으로 파일 설명자 1 에 기록 되 었 습 니 다.파일 설명자 0, 1, 2 는 표준 입력, 표준 출력, 표준 오류 출력 과 관련 이 있 습 니 다. 이것 은 셸 과 많은 응용 프로그램의 관례 일 뿐 커 널 과 는 무관 합 니 다.다음 스 트림 으로 문 제 를 설명 할 수 있 습 니 다. (ps: 스 트림 관 계 는 아니 지만 이해 에 도움 이 됩 니 다) printf - > stdout - > STDOUTFILENO (1) - > 터미널 (tty) printf 의 마지막 출력 은 터미널 장치 에 있 습 니 다. 파일 설명자 1 은 현재 터미널 을 가리 키 며 이렇게 이해 할 수 있 습 니 다: STDOUTFILENO = open("/dev/tty", O_RDWR); dup 2 사용 후 STDOUTFILENO 는 터미널 장 치 를 가리 키 지 않 고 connfd 를 가리 키 기 때문에 printf 의 출력 은 마지막 으로 connfd 에 기록 되 었 습 니 다.너무 아름 답지 않 아 요?:)4. CGI 프로그램의 fork 하위 프로 세 스에 서 STDOUT 를 복원 하 는 방법FILENO 가 이곳 을 볼 수 있다 면 인내심 에 감 사 드 립 니 다. 많은 사람들 이 복잡 하 게 느 낄 수 있다 는 것 을 알 고 있 습 니 다. 사실은 복잡 한 문 제 는 작은 문제 들 의 집합 입 니 다.그래서 작은 문제 하나 하 나 를 알 아내 면 됩 니 다. 3 절 에서 "STDOUT" 라 고 말 했 습 니 다.FILENO 는 connfd 소켓 으로 재 설정 되 었 습 니 다. 가끔 은 CGI 프로그램 에서 배경 스 크 립 트 를 호출 하여 실행 하려 고 할 수도 있 습 니 다. 이 스 크 립 트 들 은 입 출력 이 있 을 수 있 습 니 다. fork 를 알 고 난 후에 하위 프로 세 스 는 부모 프로 세 스 의 모든 파일 설명 자 를 계승 하기 때문에 이 각본 의 입 출력 은 우리 가 원 하 는 대로 터미널 장치 에 출력 되 지 않 습 니 다.이것 은 분명히 웹 페이지 의 출력 을 어 지 럽 힐 것 이다.그럼 어떻게 STDOUT 를 회복 합 니까?FILENO 는 터미널 과 연 결 됩 니까?방법 1: dup 2 전에 기 존 파일 설명 자 를 저장 하고 복원 합 니 다.코드 구현 은 다음 과 같 습 니 다: savefd = dup (STDOUT FILENO);/ * savefd 는 이때 터미널 * / dup 2 (connfd, STDOUT FILENO) 를 가리 키 고 있 습 니 다. /*STDOUT_FILENO (1) 는 connfd * /.............................................................................STDOUT_FILENO (1) 복구 지향 savefd * / CGI 프로그램 이 이 방법 을 사용 할 수 없어 유감 입 니 다. dup 2 는 CGI 프로그램 에서 이 루어 진 것 이 아니 라 웹 서버 에서 이 루어 진 것 이기 때문에 웹 서버 를 수정 하 는 것 은 좋 은 생각 이 아 닙 니 다.방법 2: 근본 을 추적 하여 현재 단말 기 를 열 어 STDOUT 회복FILENO。 제3 절의 흐름 도 분석, STDOUTFILENO 는 어떻게 단말기 와 연 결 됩 니까?우리 가 다시 한 번 하면 되 잖 아. 코드 는 다음 과 같 아. ttyfd = open ("/ dev / tty", O RDWR);dup2(ttyfd, STDOUT_FILENO); close(ttyfd); /dev / tty 는 프로그램 이 실행 중인 터미널 입 니 다. 이것 은 하나의 방법 으로 얻어 야 합 니 다.실천 은 이런 방법 이 실행 가능 하 다 는 것 을 증명 하지만, 나 는 항상 약간 타당 하지 않다 고 느낀다. 왜 그런 지 모 르 겠 지만, 아마도 잠재 적 인 문제 들 이 아직 나타 나 지 않 았 을 것 이다.
dup 기반 Liux 의 dup 2 함수 구현 (APUE 연습 문제 3.2) 방법
int ud_dup2(const int ofd, const int nfd) {
// ,
if(ofd == nfd) return ofd;
int pid = getpid();
char *pathname = malloc(sizeof(char) * 128);
sprintf(pathname, "/proc/%d/fd/%d", getpid(), nfd);
// ,
if(!access(pathname, F_OK)) close(nfd);
int tmp;
int max = sysconf(_SC_OPEN_MAX);
int fds[max], i = 0;
// ,
if(max < nfd) return -1;
do {
tmp = dup(ofd);
//dup
if(tmp < 0) break;
fds[i ++] = tmp;
} while(tmp < nfd);
// , i , , , ,
if(tmp == nfd) i --;
//
while(i-- >= 0) close(fds[i]);
if(tmp != nfd) return -1;
return nfd;
}
방법 http://pnig0s1992.blog.51cto.com/393390/819830 상세 하 게 해석 하 다http://blog.csdn.net/songyang516/article/details/6791552
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다: