2011-02-02 46 views
9

Tôi đang làm việc trên một daemon Linux và có một số vấn đề với stdin/stdout. Thông thường vì bản chất của một daemon bạn không có bất kỳ stdin hoặc stdout nào. Tuy nhiên, tôi có một hàm trong daemon được gọi khi daemon chạy lần đầu tiên để xác định các tham số khác nhau được yêu cầu cho daemon để chạy thành công. Khi chức năng này được gọi là thiết bị đầu cuối trở nên quá chậm chạp đến mức tôi phải khởi chạy một trình bao riêng biệt và tiêu diệt daemon bằng đầu để nhận được lời nhắc đáp ứng. Bây giờ tôi nghi ngờ rằng điều này có cái gì để làm với quá trình forking đóng stdin/stdout nhưng tôi không khá chắc chắn làm thế nào tôi có thể làm việc xung quanh này. Nếu các bạn có thể làm sáng tỏ tình hình sẽ được đánh giá cao nhất. Cảm ơn.Một Daemon Linux và STDIN/STDOUT

Edit:

int main(argc, char *argv[]) { 

/* setup signal handling */ 

/* check command line arguments */ 

pid_t pid, sid; 

pid = fork(); 

if (pid < 0) { 
exit(EXIT_FAILURE); 
} 

if(pid > 0){ 
exit(EXIT_SUCCESS); 
} 

sid = setsid(); 

if(sid < 0) { 
exit(EXIT_FAILURE); 
} 

umask(027); 

/* set syslogging */ 

/* do some logic to determine wether we are running the daemon for the first time and if we are call the one time function which uses fgets() to recieve some input */ 

while(1) { 

/* do required work */ 

} 

/* do some clean up procedures and exit */ 

return 0; 
} 

Các bạn đề cập đến cách sử dụng một tập tin cấu hình. Đây là chính xác những gì tôi làm để lưu trữ các thông số nhận được thông qua đầu vào. Tuy nhiên, tôi vẫn cần phải có được những thứ này từ người dùng thông qua stdin. Logic để xác định xem chúng ta đang chạy lần đầu tiên có dựa trên sự tồn tại của tệp cấu hình hay không.

+1

Chúng tôi không có ý tưởng nếu không nhìn thấy một số mã. Nhưng có vẻ như bạn đang làm sai. Bạn có nói rằng bạn muốn daemon để có thể mất stdin/stdout? Bạn sẽ phải ống chúng trên một ổ cắm hoặc một cái gì đó. – Falmarri

+0

Có Falmarri nhưng chỉ khi mà chức năng cụ thể được gọi là như tôi đã nói là một điều một lần. Trong mã của tôi, tôi gọi hàm này sau khi tôi fork(); một quy trình mới. – Error1f1f

+2

tại sao không sử dụng tệp cấu hình? –

Trả lời

3

Các bạn đề cập đến việc sử dụng tệp cấu hình. Đây là chính xác những gì tôi làm để lưu trữ các thông số nhận được thông qua đầu vào. Tuy nhiên, tôi vẫn cần phải có được những thứ này từ người dùng thông qua stdin. Logic để xác định xem chúng ta đang chạy lần đầu tiên có dựa trên sự tồn tại của tệp cấu hình hay không.

Thay vì đọc stdin, có người sử dụng viết các tập tin cấu hình tự; kiểm tra sự tồn tại của nó trước khi bỏ qua và thoát ra nếu có lỗi. Bao gồm một tập tin cấu hình mẫu với daemon, và tài liệu định dạng của nó trong manpage của daemon của bạn. Bạn do có trang manpage, phải không? Tệp cấu hình của bạn văn bản, phải không?

Ngoài ra, logic daemon của bạn thiếu một bước quan trọng. Sau khi forking, nhưng trước khi gọi setsid, bạn cần đóng fds 0, 1 và 2 và mở lại chúng thành /dev/null (làm không cố gắng thực hiện việc này với fclosefopen). Điều đó sẽ khắc phục vấn đề thiết bị đầu cuối chậm chạp của bạn.

+0

ouch dựa vào người dùng để ghi tệp cấu hình? Ngoài ra tôi đã thử làm bất kỳ I/O trước khi quá trình forking và tôi vẫn nhận được cùng một vấn đề với các thiết bị đầu cuối chậm chạp. – Error1f1f

+0

Có, hoàn toàn dựa vào người dùng để ghi tệp cấu hình. Đó là cách thực hiện điều này với Unix. Quay lại thiết bị đầu cuối chậm chạp, xem chỉnh sửa. – zwol

+0

"Không * cố gắng thực hiện điều này bằng' fclose' và 'fopen'." Tại sao vậy, và làm thế nào * nên * chúng tôi cố gắng để làm điều này? –

1

Thiết kế của bạn sai. Các quy trình Daemon không nên lấy đầu vào thông qua stdin hoặc cung cấp đầu ra tới stdout/stderr. Bạn sẽ đóng những mô tả đó như là một phần của giai đoạn làm daemon. Daemon nên lấy tham số cấu hình từ dòng lệnh, một tệp cấu hình, hoặc cả hai. Nếu thời gian chạy-đầu vào là bắt buộc, bạn sẽ phải đọc một tệp, mở một ổ cắm, vv, nhưng điểm của một daemon là nó sẽ có thể chạy và làm điều mà không có người dùng đang có mặt tại bàn điều khiển.

+3

Trừ khi đây là một daemon chạy bởi inetd ... :-) – mateusza

14

Thông thường, đầu vào chuẩn của daemon phải được kết nối với /dev/null, để nếu có bất kỳ điều gì được đọc từ đầu vào tiêu chuẩn, bạn sẽ nhận được EOF ngay lập tức. Thông thường, đầu ra tiêu chuẩn phải được kết nối với một tệp - hoặc tệp nhật ký hoặc /dev/null. Sau này có nghĩa là tất cả các ghi sẽ thành công, nhưng sẽ không có thông tin nào được lưu trữ. Tương tự, lỗi chuẩn phải được kết nối với /dev/null hoặc tới tệp nhật ký.

Tất cả các chương trình, kể cả daemon, đều có quyền giả định rằng stdin, stdout và stderr là các luồng tệp được mở thích hợp.

Nó thường là thích hợp cho một daemon để kiểm soát nơi đầu vào của nó đến từ và đầu ra đi đến. Có ít khi có sự xuất hiện của các dữ liệu khác từ /dev/null. Nếu mã được viết để tồn tại mà không có đầu ra tiêu chuẩn hoặc lỗi chuẩn (ví dụ, nó sẽ mở một kênh log tiêu chuẩn, hoặc có thể sử dụng syslog(3)) thì nó có thể thích hợp để đóng stdout và stderr. Nếu không, nó có thể thích hợp để chuyển hướng chúng đến /dev/null, trong khi vẫn ghi nhật ký thư vào tệp nhật ký. Ngoài ra, bạn có thể chuyển hướng cả stdout và stderr sang một tệp nhật ký - hãy cẩn thận các tệp nhật ký đang phát triển liên tục.

Thời gian phản hồi chậm chạp không thể xảy ra của bạn có thể là do chương trình của bạn không chú ý đến EOF trong vòng lặp đọc ở đâu đó. Nó có thể được nhắc nhở cho người dùng nhập vào/dev/null, và đọc một phản hồi từ/dev/null, và không nhận được một 'y' hoặc 'n' trở lại, nó cố gắng một lần nữa, mà nhai lên hệ thống của bạn khủng khiếp. Tất nhiên, mã là thiếu sót trong việc không xử lý EOF, và đếm số lần nó nhận được một phản ứng không hợp lệ và dừng lại là ngớ ngẩn sau một số lượng hợp lý của các nỗ lực (16, 32, 64). Chương trình nên đóng cửa cửa hàng một cách an toàn và an toàn nếu nó dự kiến ​​một đầu vào có ý nghĩa và tiếp tục không nhận được nó.

1

Sử dụng tệp cấu hình. Không sử dụng STDIN hoặc STDOUT với một daemon. Daemon có nghĩa là chạy trên nền mà không có tương tác của người dùng.

1

Nếu bạn nhấn mạnh vào việc sử dụng đầu vào stdin/bàn phím để kích hoạt trình nền (ví dụ:để nhận được một số cụm từ mật khẩu bạn không muốn lưu trữ trong một tệp), hãy xử lý tất cả I/O trước số fork().

+0

Tôi cũng nghĩ về điều đó và chỉ cần thử nó để xác nhận và tôi vẫn nhận được cùng một vấn đề với các thiết bị đầu cuối chậm chạp. Nó khá là khó hiểu với tôi. – Error1f1f

+0

Đoạn mã của bạn có vẻ đề xuất khác. Vui lòng chia sẻ mã thực nếu bạn muốn giải quyết vấn đề. – mvds

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