Да, нет абсолютно ничего мешающего Вам выполнить ту команду.
Однако совершенно возможно, что в процессе выполнения его, система станет нестабильной, и Вы получите панику ядра. Я не могу думать ни о чем, что заставило бы это происходить, и я сделал это, не сталкиваясь с упомянутой проблемой, но это теоретически возможно (из-за файлов с отображенной памятью).
Отметьте, хотя, что, как только команда завершается, и Вы роняетесь к оболочке, Вы не сможете сделать единственную вещь.
Другая возможная причина этого сбоя состояла бы в том, если у Вас есть сторожевое выполнение (если Вы не знаете, каков сторожевой таймер, у Вас, вероятно, нет одного). Сторожевой таймер, очень вероятно, перестанет работать, и когда он сделает систему, перезагрузит.
Ваш вопрос частично основан на плохом соглашении о присвоении имен. "Поток управления" в ядре - говорит, процесс в пользователе - говорят. Таким образом, когда Вы читаете, что vfork "вызывающий поток приостановлен", думают "процесс" (или "тяжелый поток", если Вам нравится), не, "распараллеливают" как в "многопоточном процессе".
vfork
семантика была определена для очень общего падежа, где процесс (оболочка чаще всего) разветвится, путаница с некоторыми дескрипторами файлов, и затем exec
другой процесс на месте. Люди ядра поняли, что они могли сохранить огромный объем копирования страницы наверху, если бы они пропустили копию начиная с exec
просто собирался выбросить те скопированные страницы. У vforked ребенка действительно есть его собственная таблица дескрипторов файлов в ядре, таким образом управляя, который не влияет на родительский процесс, сохраняя семантику fork
неизменный.
Учитывая более точное определение "потока ядра управления", ответ на может, они работать параллельно ясно
Как родитель знает, что ребенок вышел?
Что касается последнего вопроса, я подозревал бы, что ядро будет обнаруживать дочерние операции стека, вовлеченные в возврат, и сигнализировать ребенку с неуловимым сигналом или просто уничтожать его, но я не знаю детали.
Я не программист линукса, но столкнувшись сегодня с тем же вопросом, я сделал следующий тест:
#include<unistd.h>
#include<signal.h>
#include<errno.h>
#include<fcntl.h>
#include<cassert>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#include<fstream>
#include<sstream>
#include<list>
using namespace std;
int single_talk(int thread_id){
fprintf(stderr,"thread %d before fork @%d\n",thread_id,time(0));
int pid=vfork();
if(-1==pid){
cerr << "failed to fork: " << strerror(errno) << endl;
_exit(-3);//serious problem, can not proceed
}
sleep(1);
fprintf(stderr,"thread %d fork returned %d @%d\n",thread_id,pid,time(0));
if(pid){//"CPP"
fprintf(stderr,"thread %d in parent\n",thread_id);
}else{//"PHP"
sleep(1);
fprintf(stderr,"thread %d in child @%d\n",thread_id,time(0));
if(-1 == execlp("/bin/ls","ls",(char*)NULL)){
cerr << "failed to execl php : " << strerror(errno) << endl;
_exit(-4);//serious problem, can not proceed
}
}
}
void * talker(void * id){
single_talk(*(int*)id);
return NULL;
}
int main(){
signal(SIGPIPE,SIG_IGN);
signal(SIGCHLD,SIG_IGN);
const int thread_count = 44;
pthread_t thread[thread_count];
int thread_id[thread_count];
int err;
for(size_t i=0;i<thread_count;++i){
thread_id[i]=i;
if((err = pthread_create(thread+i,NULL,talker,thread_id+i))){
cerr << "failed to create pthread: " << strerror(err) << endl;
exit(-7);
}
}
for(size_t i=0;i<thread_count;++i){
if((err = pthread_join(thread[i],NULL))){
cerr << "failed to join pthread: " << strerror(err) << endl;
exit(-17);
}
}
}
Я скомпилировал его с g++ -pthread -o repro.cpp
и запустил с ./repro
.
Что я вижу на выходе, так это то, что всё происходит одновременно в раундах: сначала все pthreads запускают vfork, потом все ждут секунду, потом "просыпаются" в дочерней процессной реальности, потом все дети запускают exec(), потом наконец-то просыпаются все родители.
Для меня это доказывает, что если один из pthread'ов вызывает vfork, то он не приостанавливает работу других pthread'ов - если бы это было так, то они не смогли бы вызвать vfork() до тех пор, пока не будет вызвана функция exec().
When child process is spawned is parent process suspended?
Да.
If yes why?
Поскольку родительский и дочерний узлы используют совместное адресное пространство. В частности, адресное пространство стека. Если родитель попытается продолжить, он, скорее всего, вызовет другую функцию и уничтожит стек вызовов дочернего процесса. Таким образом, он не запускается до exec()
или _exit()
They can run in parallel (like Threads)? After all both threads and process call the same clone() function.
Действительно. Приостанавливается только вызывающий поток. См. выше.
How does parent process know that the child has exited?
Он вызывает wait4()
. Но скорее вы спрашиваете, откуда родитель знает, что нужно продолжать. Это не так. Ядро делает его снова работоспособным, когда происходит любое из двух определенных событий.
And what will happen if we return from a child process?
vfork()
возвращается в освобожденный кадр стека, а следующий return;
— это быстрый путь к неопределенному поведению.
What will happen if we return from a child process?
«Это действительно не работает, однако, чтобы вернуться во время работы в контексте ребенка из процедура, которая вызвала vfork ()с момента возможного возврата из vfork ()затем вернется к несуществующему кадру стека."
Я не понимаю это буквально. Байты в области стека буквально не исчезают после каждой инструкции POP (или RETURN ). Однако если вы вернетесь, продолжите работу и выполните инструкцию PUSH (или CALL ), она заменит предыдущее значение в стеке.
Это всего лишь один яркий пример странных вещей, которые произойдут в целом.если вы вызовете vfork()
, а затем сделаете что-нибудь, чтобы изменить какую-либо часть памяти вашего процесса.
[Технически я предполагаю то же поведение, что и в Linux. Другое поведение vfork ()было технически разрешено POSIX. Я не знаю, нашел ли кто-нибудь применение технической гибкости POSIX, кроме предоставления vfork (), который идентичен fork ()].
sleep()
реализован. – msw 23.10.2014, 19:41