GNU/Linux >> Belajar Linux >  >> Linux

Mengapa popen() memanggil shell untuk mengeksekusi suatu proses?

Versi 2004 dari POSIX system() dokumentasi memiliki alasan yang mungkin berlaku untuk popen() demikian juga. Perhatikan batasan yang disebutkan pada system() , terutama yang menyatakan "bahwa ID prosesnya berbeda":

RASIONAL

...

Ada tiga tingkat spesifikasi untuk fungsi system(). Standar ISO C memberikan yang paling dasar. Itu membutuhkan fungsi yang ada, dan menentukan cara bagi aplikasi untuk menanyakan apakah juru bahasa perintah ada. Tidak disebutkan apa pun tentang bahasa perintah atau lingkungan tempat perintah tersebut ditafsirkan.

IEEE Std 1003.1-2001 memberikan batasan tambahan pada system(). Itu membutuhkan jika ada juru bahasa perintah, lingkungan harus seperti yang ditentukan oleh fork() dan exec. Ini memastikan, misalnya, bahwa close-on-exec berfungsi, bahwa kunci file tidak diwariskan, dan ID prosesnya berbeda. Ini juga menentukan nilai kembalian dari system() saat baris perintah dapat dijalankan, sehingga memberi aplikasi beberapa informasi tentang status penyelesaian perintah.

Terakhir, IEEE Std 1003.1-2001 mengharuskan perintah untuk ditafsirkan seperti dalam bahasa perintah shell yang ditentukan dalam volume Shell and Utilities dari IEEE Std 1003.1-2001.

Perhatikan beberapa referensi ke "Standar ISO C". Versi terbaru standar C mengharuskan string perintah diproses oleh "pemroses perintah" sistem:

7.22.4.8 system fungsi

Sinopsis

#include <stdlib.h>
int system(const char *string);

Deskripsi

Jika string adalah pointer null, system fungsi menentukan apakah lingkungan host memiliki prosesor perintah. Jika string bukan penunjuk null, system fungsi melewati string yang ditunjuk oleh string kepada pemroses perintah untuk dieksekusi dengan cara yang pelaksanaannya harus didokumentasikan; ini kemudian dapat menyebabkan program memanggil system untuk berperilaku dengan cara yang tidak sesuai atau untuk menghentikan.

Pengembalian

Jika argumennya adalah pointer null, system function mengembalikan nol hanya jika prosesor perintah tersedia. Jika argumennya bukan penunjuk nol, dan system functiontidak mengembalikan, mengembalikan nilai yang ditentukan implementasi.

Karena standar C mengharuskan sistem "pemroses perintah" digunakan untuk system() panggilan, saya menduga bahwa:

  1. Di suatu tempat ada persyaratan di POSIX yang mengikat popen() ke system() implementasi.
  2. Lebih mudah menggunakan kembali "pemroses perintah" sepenuhnya karena ada juga persyaratan untuk dijalankan sebagai proses terpisah.

Jadi ini adalah jawaban fasih yang dihapus dua kali.


Memanggil shell memungkinkan Anda melakukan semua hal yang dapat Anda lakukan di shell.Misalnya,

FILE *fp = popen("ls *", "r");

dimungkinkan dengan popen() (memperluas semua file di direktori saat ini). Bandingkan dengan:

execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});

Anda tidak dapat menjalankan ls dengan * sebagai argumen karena exec(2) akan menafsirkan * secara harfiah.

Demikian pula, pipa (| ), pengalihan (> , < , ...), dll., dimungkinkan dengan popen .

Jika tidak, tidak ada alasan untuk menggunakan popen jika Anda tidak membutuhkan shell - itu tidak perlu. Anda akan berakhir dengan proses shell ekstra dan semua hal yang bisa salah di shell bisa salah dalam program Anda (misalnya, perintah yang Anda berikan dapat diinterpretasikan secara tidak benar oleh shell dan masalah keamanan umum). popen() dirancang seperti itu. fork + exec solusi lebih bersih tanpa masalah yang terkait dengan shell.


Jawaban fasih adalah karena standar POSIX ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ) mengatakan demikian. Atau lebih tepatnya, ia mengatakan bahwa ia harus berperilaku seolah-olah argumen perintah diteruskan ke /bin/sh untuk interpretasi.

Jadi saya kira implementasi yang sesuai dapat, pada prinsipnya, juga memiliki beberapa fungsi perpustakaan internal yang akan menginterpretasikan perintah shell tanpa harus melakukan fork dan menjalankan proses shell yang terpisah. Saya sebenarnya tidak mengetahui penerapan semacam itu, dan saya menduga memperbaiki semua kasus sudut akan sangat rumit.


Linux
  1. Bagaimana Cara Menjalankan Perintah di Shell Tanpa Menyimpannya ke Riwayat? [Kiat Linux]

  2. Mengapa Bashrc Memeriksa Apakah Shell Saat Ini Interaktif?

  3. Mengapa Shell Login 'Sudo -i' Memecah Argumen String Perintah Di Sini-doc?

  1. Apa itu POSIX? Mengapa Penting bagi Pengguna Linux/UNIX?

  2. Mengapa "ls" Membutuhkan Proses Terpisah Untuk Dieksekusi?

  3. Mengapa Ctrl + V tidak menempel di Bash (Linux shell)?

  1. Mengapa Pergantian Perintah Shell Melahap A Trailing Newline Char?

  2. Mengapa Perintah Berikut Membunuh Sistem?

  3. Mengapa pipa shell ini keluar?