2012-01-31 29 views
23

Tôi đang viết một hàm, trong đó, đưa ra một đối số, hoặc chuyển hướng stdout tới tệp hoặc đọc stdin từ tệp. Để làm điều này, tôi đóng bộ mô tả tập tin được liên kết với stdout hoặc stdin, để khi tôi mở tập tin nó mở ra dưới phần mô tả mà tôi vừa đóng. Điều này làm việc, nhưng vấn đề là một khi điều này được thực hiện, tôi cần phải khôi phục lại stdout và stdin để những gì họ thực sự cần được.Mở lại mô tả tệp stdout và stdin sau khi đóng chúng

Những gì tôi có thể làm cho stdout là mở ("/ dev/tty", O_WRONLY); Nhưng tôi không chắc tại sao nó lại hoạt động, và quan trọng hơn là tôi không biết câu lệnh tương đương cho stdin.

Vì vậy, tôi có, cho stdout

close(1); 
if (creat(filePath, O_RDWR) == -1) 
{ 
    exit(1); 
} 

và cho stdin

close(0); 
if (open(filePath, O_RDONLY) == -1) 
{ 
    exit(1); 
} 
+2

man 'dup' và' dup2' –

+0

'O_RDWR' là cho tham số' mở' 'cờ' không cho tham số' tạo' 'mode'. –

Trả lời

34

Bạn nên sử dụng dup() và dup2() để sao chép một bộ mô tả tệp.

int stdin_copy = dup(0); 
int stdout_copy = dup(1); 
close(0); 
close(1); 

int file1 = open(...); 
int file2 = open(...); 

< do your work. file1 and file2 must be 0 and 1, because open always returns lowest unused fd > 

close(file1); 
close(file2); 
dup2(stdin_copy, 0); 
dup2(stdout_copy, 1); 
close(stdin_copy); 
close(stdout_copy); 

Tuy nhiên, có một chi tiết nhỏ bạn có thể muốn cẩn thận với (từ người đàn ông dup):

Hai mô tả không chia sẻ cờ mô tả tập tin (các gần-on-execflag) . Cờ close-on-exec (FD_CLOEXEC; xem fcntl (2)) cho bộ mô tả trùng lặp bị tắt.

Nếu đây là vấn đề, bạn có thể phải khôi phục cờ đóng-trên-exec, có thể sử dụng dup3() thay vì dup2() để tránh điều kiện chủng tộc.

Ngoài ra, hãy lưu ý rằng nếu chương trình của bạn đa luồng, các chủ đề khác có thể vô tình ghi/đọc vào stdin/stdout đã được remapped của bạn.

+0

Cảm ơn, điều này thực sự đã giúp tôi! –

+2

Có nhiều vấn đề khác nếu bạn đa luồng - nếu một luồng khác mở một tệp giữa 'close (0)' (hoặc 'close (1)') và 'open (...)' tương ứng, thì tệp của nó sẽ trở thành stdin (hoặc stdout). Tốt hơn là sử dụng 'dup2()' (hoặc 'dup3') để buộc bộ mô tả tập tin là 0 (hoặc 1), thay vì dựa vào hành vi" không sử dụng thấp nhất ". – psmears

14

Tôi nghĩ bạn có thể "cứu" các descriptor trước khi chuyển hướng:

int save_in, save_out; 

save_in = dup(STDIN_FILENO); 
save_out = dup(STDOUT_FILENO); 

Sau đó bạn có thể sử dụng dup2 để khôi phục chúng:

/* Time passes, STDIN_FILENO isn't what it used to be. */ 
dup2(save_in, STDIN_FILENO); 

Tôi không làm bất kỳ kiểm tra lỗi trong ví dụ đó - bạn cần.

0

Bạn có thể tạo quy trình con và chỉ thiết lập chuyển hướng bên trong con. Sau đó chờ đứa trẻ chấm dứt, và tiếp tục làm việc trong tiến trình cha mẹ. Bằng cách đó bạn không phải lo lắng về việc đảo ngược chuyển hướng của bạn cả.

Chỉ cần tìm các ví dụ về mã bằng fork() và wait().

Các vấn đề liên quan