2015-04-16 12 views
6

Giả sử, tôi có hai chương trình - input.c & output.c Tất cả những gì tôi muốn làm là gửi một số tải trọng/ký tự trong định dạng "nửa kim tự tháp" sang định dạng khác bằng hàm execl() .C - Ký tự rác trên đầu ra

input.c

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 

#define SIZE 1024 

int length; 

int main(int argc, char *argv[]) 
{ 
    pid_t pid; 
    char *target; 
    //char payload[length+1]; 
    char payload[SIZE + 1]; 
    int status; 
    int i = 0; 

    if(argc < 2) 
    { 
     printf("Usage %s <length> <target>\n", argv[0]); 
     exit(EXIT_FAILURE); 
    } 

    length = atoi(argv[1]); 
    target = argv[2]; 

    while(i < length) 
    { 
     pid = fork(); 

     if(pid != 0) 
     { 
      waitpid(-1, &status, 0); 
      //exit(0); 
     } 

     if(pid == 0) 
     { 
      payload[i] = 'A'; 
      payload[i + 1] = '\0'; 
      execl(target, target, payload, NULL); 
      //printf("%s\n", payload); 
     } 
     ++i; 
    } 
    return 0; 
} 

đoạn nhận xét là chỉ dành riêng cho mục đích gỡ lỗi. Vì bạn có thể thấy (khi đang cố gắng), khi bạn muốn in nó, mọi thứ đều hoạt động bình thường.

output.c (hoặc nếu bạn muốn 'target.c')

#include <stdio.h> 
#include <string.h> 

int main(int argc, char *argv[]) 
{ 
    char buffer[30]; 
    strncpy(buffer, argv[1], sizeof(buffer)); 
    printf("Output: %s\n", buffer); 

    return 0; 
} 

Khi tôi biên dịch input.c như:

gcc input.c -o input 

& output.c :

gcc output.c -o output 

Ok. Bây giờ, mọi thứ đã được chuẩn bị. Hãy nói rằng, tôi muốn gửi một tải trọng - chiều dài 6

./input 6 ./output 

nhưng tất cả tôi nhận được về sản lượng chỉ này (hoặc đơn giản là với một nhân vật thuyền):

Output: A 
Output: 0A 
Output: 0,A 
Output: 0,�A 
Output: 0,�8A 
Output: 0,�8�A 

tôi đã cố gắng rất nhiều mọi thứ, nhưng tất cả chúng đều thất bại và đầu ra vẫn như cũ, như bạn có thể thấy ở trên.

Tôi sẽ rất biết ơn nếu có ai có thể giúp tôi và có thể chỉ cho tôi vấn đề ở đâu. Có thể có vấn đề trong việc sử dụng các hàm fork() và execl() cùng nhau không?

Trả lời

5

Got nó, bạn không nên cập nhật payloadtrong mã khối đứa trẻ ...

Dưới đây là cách khắc phục (không thể kiểm tra nó bây giờ):

while(i < length) 
    { 
     pid = fork(); 
     payload[i] = 'A'; 
     payload[i + 1] = '\0'; 

     if(pid != 0) 
     { 
      waitpid(-1, &status, 0); 
      //exit(0); 
     } 

     if(pid == 0) 
     { 
      execl(target, target, payload, NULL); 
      //printf("%s\n", payload); 
     } 
     ++i; 
    } 

[Gỡ bỏ bản án không liên quan]

EDIT (giải thích bổ sung): payload cập nhật phải ở trong cả hai mã cấp độ gốc và mã con. Nếu bạn không hiểu tại sao, tôi có thể giải thích thêm.

EDIT2 (theo yêu cầu). Bạn muốn cập nhật tải trọng cho tiếp theo quy trình con chia hai. Trong mã của bạn, tất cả mã con được thay thế bằng execl() thành mã target. Vì vậy, fork() được thực hiện chỉ bởi quá trình cha mẹ đầu tiên (gốc).

Bạn phải cập nhật tải trọng của cha mẹ đầu tiên và làm cho nó có thể truy cập được quá tất cả trẻ em.Đưa nó vào khối này sẽ không làm việc, hoặc:

// block only executed by the first parent. 
if(pid != 0) 
{ 
    waitpid(-1, &status, 0); 
} 

Vì vậy, Bạn phải cập nhật nó ở một nơi cả thể truy cập bằng các phụ huynh và trẻ em: sau khi fork(), trước khi if(pid == 0) khối.

Trong mã của bạn, bạn tăng i trong khối chung, nhưng phụ huynh payload không bao giờ được cập nhật. Vì vậy, trong khối con, ngay trước số execl(), bạn thêm 'A\0' vào cuối một chuỗi uninitialized C'.

+0

Bạn là một người đàn ông! Vâng, nó hoạt động như một nét duyên dáng Và có, nếu nó không phải là vấn đề cho bạn, tôi sẽ biết ơn vì một số lời giải thích chi tiết hơn, bởi vì tôi không nghĩ rằng tôi hiểu nó trên 100% và tôi không muốn làm một số – Yeez

+0

Ok, tôi thêm một số giải thích. h "tập luyện cho tôi. – Amessihel

+0

Hehe, tôi rất vui vì nó là như vậy. Dù sao, bây giờ tôi đang kiểm tra nó một lần nữa và tôi có thêm một câu hỏi - nếu bạn có thể trả lời. Trong trường hợp tôi thay thế strncpy với strcpy và làm "./input 80 ./output", tại sao tôi không thể nhìn thấy một nơi nào đó trên đầu ra "Segmentation fault"? Tôi chỉ tò mò thôi. – Yeez

2

Khi dĩa chương trình của bạn, nó tạo ra một quy trình mới. Quy trình mới này, sau if(pid == 0), thay đổi payload và chạy exec (nghĩa là thực hiện output, sau đó sẽ chết. Tức là, thay đổi trọng tải của bạn vẫn ở trong trẻ em và không ảnh hưởng đến quy trình gốc. Chỉ có ++i. đang nhìn thấy dữ liệu unitialized.

Move thay đổi tải trọng trước ngã ba (hoặc ít nhất là ra khỏi chỉ con khối), vì vậy nó là trong các phụ huynh là tốt.

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