2009-06-05 19 views
7

Tôi đang tìm một cách hiệu quả để truy cập (đối với cả hoạt động đọc và ghi) dung lượng bộ nhớ của tiến trình con ptraced của tôi. Kích thước của các khối được truy cập có thể thay đổi từ vài byte lên đến vài megabyte, do đó, sử dụng lệnh ptrace với PTRACE_PEEKDATAPTRACE_POKEDATA chỉ đọc một từ tại một thời điểm và chuyển ngữ cảnh mỗi khi chúng được gọi có vẻ như một sự lãng phí vô nghĩa tài nguyên. Tuy nhiên, giải pháp thay thế duy nhất mà tôi có thể tìm thấy là tệp /proc/<pid>/mem, nhưng từ lâu nó đã được thực hiện chỉ đọc.Cách chi phí thấp để truy cập vào không gian bộ nhớ của quá trình truy tìm?

Có cách nào khác (tương đối đơn giản) để thực hiện công việc đó không? Giải pháp lý tưởng sẽ bằng cách nào đó chia sẻ không gian địa chỉ của tiến trình con với cha mẹ và sau đó sử dụng cuộc gọi memcpy đơn giản để sao chép dữ liệu tôi cần theo cả hai hướng, nhưng tôi không có manh mối làm cách nào và bắt đầu từ đâu.

Bất kỳ ý tưởng nào?

+0

bạn muốn xem bất kỳ thông tin bộ nhớ nào hoặc tại một phần dữ liệu cụ thể mà bạn muốn chia sẻ? Ý tôi là, bạn muốn acess toàn bộ không gian bộ nhớ? – LB40

+0

Tôi muốn truy cập các phần dữ liệu cụ thể có vị trí, thời lượng và số lượng thay đổi mỗi lần tôi khởi chạy chương trình. Nhưng tôi nghĩ rằng việc truy cập vào toàn bộ không gian bộ nhớ của quá trình truy tìm là cách tự nhiên và dễ dàng nhất để đọc và sửa đổi chúng. – vovick

+1

ah tôi đã có câu hỏi này rất giống nhau khoảng 3 năm trước đây! =) –

Trả lời

1

Bạn có kiểm soát được quy trình con và mã nguồn của nó không? Nếu có, bạn có thể xem xét sử dụng Shared memory.

4

Nếu đây là Linux (mà thẻ đề xuất), bạn có thể chia sẻ toàn bộ không gian địa chỉ của trẻ với cha mẹ bằng cách sử dụng clone() với cờ CLONE_VM. Khi hai tiến trình chia sẻ cùng một không gian VM, tất cả các sửa đổi sẽ được hiển thị ngay lập tức giữa hai quy trình, với mức phí cơ bản bằng không.

Điều này có nghĩa là bạn không thể sau đó exec() ở trẻ em; vì nó sẽ thay thế không gian VM của cả hai quy trình.

+0

sẽ không yêu cầu truy cập vào mã nguồn của đứa trẻ để gọi clone(), hoặc bạn nhân bản() ing từ cha mẹ, và sau đó gọi ptrace() từ "chuỗi chủ đề" mới? –

+1

điều này có vẻ như là câu trả lời hay nhất, nhưng tôi không chắc chắn có thể "xâm phạm" quá trình nhắm mục tiêu mà không thể truy cập nguồn của nó hay can thiệp vào cuộc gọi, như osgx gợi ý –

0

Nếu bạn kiểm soát quá trình con, có thể bạn có thể thêm giao diện gỡ lỗi cho phép bạn ghi vào bộ nhớ được đề cập?

1

Xem xét việc tiêm một số chức năng gỡ lỗi vào quá trình ptraced và gọi nó qua ptrace_setregs. Một cái gì đó giống như cách gdb có thể chạy bất kỳ chức năng của quá trình ptraced.

Ngoài ra, bạn có thể thử tiêm một số mã vào quá trình qua LD_PRELOAD. Bạn thậm chí có thể cố gắng thực hiện công việc mà không cần ptrace, sử dụng tín hiệu.

upd1: tiêm Gdb hoặc "gọi hàm kém" khá phức tạp. Xem chức năng call_function_by_hand trong tập tin gdb-6.6.50.20070809> gdb> infcall.c đây: http://sources.debian.net/src/gdb/7.6.2-1/gdb/infcall.c?hl=462#L462

/* All this stuff with a dummy frame may seem unnecessarily complicated 
    (why not just save registers in GDB?). The purpose of pushing a dummy 
    frame which looks just like a real frame is so that if you call a 
    function and then hit a breakpoint (get a signal, etc), "backtrace" 
    will look right. Whether the backtrace needs to actually show the 
    stack at the time the inferior function was called is debatable, but 
    it certainly needs to not display garbage. So if you are contemplating 
    making dummy frames be different from normal frames, consider that. */ 

/* Perform a function call in the inferior. 
    ARGS is a vector of values of arguments (NARGS of them). 
    FUNCTION is a value, the function to be called. 
    Returns a value representing what the function returned. 
    May fail to return, if a breakpoint or signal is hit 
    during the execution of the function. 

    ARGS is modified to contain coerced values. */ 

struct value * 
call_function_by_hand (struct value *function, int nargs, struct value **args) 
{ 
... 
    frame = get_current_frame(); 
    gdbarch = get_frame_arch (frame); 

    if (!gdbarch_push_dummy_call_p (gdbarch)) 
    error (_("This target does not support function calls.")); 

    /* A cleanup for the inferior status. 
    This is only needed while we're preparing the inferior function call. */ 
    inf_status = save_infcall_control_state(); 
    inf_status_cleanup 
    = make_cleanup_restore_infcall_control_state (inf_status); 

    /* Save the caller's registers and other state associated with the 
    inferior itself so that they can be restored once the 
    callee returns. To allow nested calls the registers are (further 
    down) pushed onto a dummy frame stack. Include a cleanup (which 
    is tossed once the regcache has been pushed). */ 
    caller_state = save_infcall_suspend_state(); 
    make_cleanup_restore_infcall_suspend_state (caller_state); 
... 
    sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs, 
        target_values_type, &real_pc, &bp_addr, 
        get_current_regcache()); 
... pass args ... 
    /* Create the dummy stack frame. Pass in the call dummy address as, 
    presumably, the ABI code knows where, in the call dummy, the 
    return address should be pointed. */ 
    sp = gdbarch_push_dummy_call (gdbarch, function, get_current_regcache(), 
       bp_addr, nargs, args, 
       sp, struct_return, struct_addr); 
... 
    /* Everything's ready, push all the info needed to restore the 
    caller (and identify the dummy-frame) onto the dummy-frame 
    stack. */ 
    dummy_frame_push (caller_state, &dummy_id); 
... 
    /* Run the inferior until it stops. */ 

    e = run_inferior_call (tp, real_pc); 
    } 
0

Để đọc, đặt cược tốt nhất của bạn là để phân tích các tập tin /proc/<pid>/maps cho các địa chỉ ảo của vùng ký ức về sự quan tâm.

Sau đó, bạn có thể đọc chúng bằng cách mở /proc/<pid>/mem và thực hiện cuộc gọi read() với bộ đệm lớn trên các lĩnh vực quan tâm. Để viết, tôi chưa tìm được cách dễ dàng để viết toàn bộ khối, tôi tin rằng việc này phải liên quan đến khóa và ổn định cho quá trình con, gọi qua số ptrace() có thể đảm bảo điều này, nhưng truy cập trực tiếp vào một quy trình khác ' bộ nhớ không thể. Tôi thường viết trình bao bọc xung quanh ptrace(PTRACE_POKEDATA, ...) để phản chiếu Windows 'WriteProcessMemory().

0

bản sao hoặc mmap là những gì bạn đang tìm kiếm. mmap tệp tạm thời giữa hai quy trình và sử dụng không gian bộ nhớ đó để truyền dữ liệu qua lại.

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