2010-02-26 13 views
15

Tôi có một câu hỏi về kích thước ngăn xếp của một quá trình trên Linux. Kích thước ngăn xếp này có được xác định tại thời gian liên kết và được mã hóa trong tệp ELF không?Kích thước ngăn xếp của quá trình trên linux liên quan đến pthread, fork và exec

Tôi đã viết một chương trình in kích thước ngăn xếp của nó theo pthread_attr_getstacksize(&attr, &stacksize);. Và nếu tôi chạy chương trình này trực tiếp từ một trình bao, nó cho một giá trị khoảng 10MB. Nhưng khi tôi exec nó từ một sợi thuộc về một chương trình đa luồng, nó cho một giá trị khoảng 2MB.

Vì vậy, tôi muốn biết những yếu tố nào ảnh hưởng đến kích thước ngăn xếp của quy trình được fork and exec-được lấy từ một số quy trình gốc. Và có thể thiết lập kích thước ngăn xếp của một quá trình trong cha mẹ của nó tại thời gian chạy trước khi fork and exec đứa trẻ?
Cảm ơn bạn trước.

Trả lời

20

Như manpage cho pthread_create(3) nói:

"Trên Linux/x86-32, ngăn xếp mặc định kích thước cho một chủ đề mới là 2 MB", trừ khi giới hạn RLIMIT_STACK tài nguyên (ulimit -s) được thiết lập: trong trường hợp đó, "nó xác định kích thước ngăn xếp mặc định của chủ đề mới".

Bạn có thể kiểm tra thực tế này bằng cách lấy giá trị hiện tại của RLIMIT_STACK với getrlimit(2), như trong chương trình sau đây:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/resource.h> 

int main() 
{ 
    /* Warning: error checking removed to keep the example small */ 
    pthread_attr_t attr; 
    size_t stacksize; 
    struct rlimit rlim; 

    pthread_attr_init(&attr); 
    pthread_attr_getstacksize(&attr, &stacksize); 
    getrlimit(RLIMIT_STACK, &rlim); 
    /* Don't know the exact type of rlim_t, but surely it will 
     fit into a size_t variable. */ 
    printf("%zd\n", (size_t) rlim.rlim_cur); 
    printf("%zd\n", stacksize); 
    pthread_attr_destroy(&attr); 

    return 0; 
} 

Đây là kết quả khi cố gắng chạy nó (biên soạn để a.out) từ dòng lệnh :

$ ulimit -s 
8192 
$ ./a.out 
8388608 
8388608 
$ ulimit -s unlimited 
$ ./a.out 
-1 
2097152 
$ ulimit -s 4096 
$ ./a.out 
4194304 
4194304 
+3

Ngoài ra, linux tự động phát triển ngăn xếp khi cần - nhưng bạn có giới hạn về giới hạn này, cũng như giới hạn về không gian địa chỉ có sẵn trong các khu vực có thể phát triển. – nos

+1

nos, chỉ dành cho chủ đề chính, phải không? – osgx

1

Theo man page for fork(), "Quy trình con được tạo bằng một chuỗi duy nhất — được gọi là ngã ba()".

Vì vậy, kích thước ngăn xếp của chuỗi chính cho quá trình con sẽ là kích thước ngăn xếp của chuỗi gọi fork().

Tuy nhiên, khi one of the exec() functions được gọi (cuối cùng gọi execve() để thực hiện công việc thực), hình ảnh quy trình được thay thế bằng chương trình mới. Tại thời điểm đó, ngăn xếp được tạo lại theo giới hạn mềm kích thước ngăn xếp (hạt nhân 2.6.23 trở lên), có thể được nhìn thấy bằng cách gọi getrlimit(RLIMIT_STACK, &rlimitStruct).

Bạn có thể kiểm soát điều này trước khi gọi exec bằng cách đặt giới hạn mềm bằng cách sử dụng setrlimit(RLIMIT_STACK, &rlimitStruct) (với điều kiện bạn không cố gắng tăng giới hạn cứng hoặc đặt giới hạn mềm cao hơn giới hạn cứng).