2008-08-19 32 views
25

Làm thế nào để bạn chạy một chương trình bên ngoài và chuyển các tham số dòng lệnh bằng cách sử dụng C? Nếu bạn phải sử dụng API hệ điều hành, hãy bao gồm giải pháp cho Windows, Mac và Linux.Làm thế nào để bạn sinh ra một tiến trình khác trong C?

+2

Tôi nghĩ bạn cần phải viết lại câu hỏi của mình - việc mở một quy trình bên ngoài không phải là * chính xác * giống như việc sinh ra một quy trình khác ... có sự khác biệt. –

Trả lời

10
#include <stdlib.h> 

int main() 
{ 
    system("echo HAI"); 

    return 0; 
} 
+6

Không bao giờ sử dụng hệ thống. Nó là xa đa luồng an toàn mà nó sẽ cắn bạn cứng và trong rác của bạn. Ví dụ, các lỗi xử lý tín hiệu là một số vấn đề khó chịu nhất và "hệ thống" đầy. – Lothar

1

Một giải pháp là các chức năng hệ thống được định nghĩa trong stdlib.h

int system(const char *string); 

system api example

4

Trên UNIX, tôi nghĩ rằng về cơ bản bạn cần đến ngã ba nó nếu bạn muốn quá trình sinh ra để chạy vô tư từ của bạn spawing một: Ví dụ nếu bạn không muốn quá trình sinh sản của bạn được chấm dứt khi bạn thoát khỏi quá trình sinh sản của bạn.

Here is a trang giải thích tất cả sự khác biệt tinh tế giữa Fork, System, Exec.

Nếu bạn làm việc trên Win, Mac và Linux, tôi có thể giới thiệu bạn Qt Framework and its QProcess object, nhưng tôi không biết đó có phải là tùy chọn cho bạn hay không. Những lợi thế tuyệt vời là bạn sẽ có thể biên dịch cùng mã trên cửa sổ linux và mac:

QString program = "./yourspawnedprogram"; 
QProcess * spawnedProcess = new QProcess(parent); 
spawnedProcess->start(program); 
// or spawnedProcess->startDetached(program); 

Và cho thêm, bạn thậm chí có thể giết chết quá trình con từ quá trình mẹ, và giữ liên lạc với nó thông qua một luồng.

14

Nếu bạn muốn thực hiện các thao tác phức tạp hơn, như đọc đầu ra của chương trình bên ngoài, bạn có thể được phục vụ tốt hơn bằng cuộc gọi hệ thống popen. Ví dụ, để lập trình truy cập vào một danh sách thư mục (đây là một ví dụ hơi ngớ ngẩn, nhưng hữu ích như một ví dụ), bạn có thể viết một cái gì đó như thế này:

#include <stdio.h> 

int main() 
{ 
    int entry = 1; 
    char line[200]; 
    FILE* output = popen("/usr/bin/ls -1 /usr/man", "r"); 
    while (fgets(line, 199, output)) 
    { 
    printf("%5d: %s", entry++, line); 
    } 
} 

để cung cấp cho sản lượng như thế này

1: cat1 
2: cat1b 
3: cat1c 
4: cat1f 
5: cat1m 
6: cat1s 
... 
15

nó thực sự phụ thuộc vào những gì bạn đang cố gắng để làm, chính xác, vì nó là:

  1. phụ thuộc hệ điều hành
  2. Không hoàn toàn rõ ràng những gì bạn đang cố gắng làm.

Tuy nhiên, tôi sẽ cố gắng cung cấp một số thông tin để bạn quyết định.
Trên UNIX, fork() tạo bản sao quy trình của bạn từ nơi bạn gọi là ngã ba. Nghĩa là, nếu tôi có quy trình sau:

#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
    printf("hi 2 u\n"); 
    int mypid = fork(); 

    if(0 == mypid) 
     printf("lol child\n"); 
    else 
     printf("lol parent\n"); 

    return(0); 
} 

Đầu ra sẽ trông như sau:

hi 2 u
lol con
lol mẹ

Khi bạn fork() pid được trả về trong đứa trẻ là 0, d pid được trả về trong parent là pid của trẻ. Lưu ý rằng "hi2u" chỉ được in một lần ...của số cha mẹ.

execve() và gia đình chức năng của nó hầu như luôn được sử dụng với fork().execve() và các mục tương tự sẽ ghi đè lên ngăn xếp hiện tại với tên của ứng dụng bạn chuyển đến. execve() hầu như luôn luôn được sử dụng với fork() nơi bạn nĩa một quá trình con và nếu bạn là cha mẹ bạn làm bất cứ điều gì bạn cần phải tiếp tục làm và nếu bạn là con bạn thực hiện một quy trình mới. execve() cũng hầu như luôn được sử dụng với waitpid() - waitpid mất một pid của một quá trình con và, theo nghĩa đen, chờ đợi cho đến khi đứa trẻ chấm dứt và trả lại trạng thái thoát của trẻ cho bạn.

Sử dụng thông tin này, bạn sẽ có thể viết một trình bao rất cơ bản; một trong đó có tên tiến trình trên dòng lệnh và chạy các tiến trình mà bạn yêu cầu nó. Tất nhiên, vỏ làm nhiều hơn thế, giống như đầu vào và đầu ra đường ống, nhưng bạn sẽ có thể hoàn thành những điều cơ bản bằng cách sử dụng fork(), execve()waitpid().

LƯU Ý: Đây là * nix cụ thể! Điều này sẽ KHÔNG hoạt động trên Windows.

Hy vọng điều này sẽ hữu ích.

1

Nếu bạn cần kiểm tra/đọc/phân tích cú pháp đầu ra của lệnh bên ngoài, tôi khuyên bạn nên sử dụng popen() thay vì system().

1

Nói về công thức nấu ăn phụ thuộc vào nền tảng, sử dụng Windows CreateProcess, trên Posix (Linux, Mac) sử dụng fork + execvp. Nhưng system() phải bao gồm các nhu cầu cơ bản của bạn và là một phần của thư viện chuẩn.

5

Tôi muốn đưa ra một cảnh báo lớn để không sử dụng hệ thống và 100% không bao giờ sử dụng hệ thống khi bạn viết thư viện. Nó được thiết kế cách đây 30 năm khi đa luồng không được biết đến với hệ điều hành đồ chơi có tên Unix. Và nó vẫn không thể sử dụng được ngay cả khi gần như tất cả các chương trình được đa luồng ngày nay.

Sử dụng popen hoặc thực hiện lệnh fork + execvp, tất cả những thứ khác sẽ khiến bạn gặp khó khăn trong việc xử lý tín hiệu, sự cố trong mã xử lý môi trường vv Đó là điều tà ác và xấu hổ mà câu trả lời được chọn và đánh giá cao nhất là quảng cáo sử dụng "hệ thống". Sẽ rất tốt cho việc quảng bá việc sử dụng Cocain tại nơi làm việc.

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