2015-04-05 1 views
0

Это упражнение в главе 8 «APUE» (упражнение 8.2, 2-е издание). Все упоминание:вызов функции vfork() в функции, сбитый с толку о результате

Напомним типичное расположение памяти на рисунке 7.6. Поскольку кадры стека , соответствующие каждому вызову функции, обычно хранятся в стеке, а потому, что после vfork ребенок запускается в адресном пространстве родителя, что произойдет, если вызов vfork осуществляется из функции, отличной от основной и ребенок выполняет возврат из этой функции после vfork ? Напишите тестовую программу, чтобы проверить это, и нарисуйте картину того, что происходит.

В моей программе:

static void f1(void), f2(void); 

int main(void) { 
    printf("main address: %d\n", main); 
    f1(); 
    f2(); 
    _exit(0); 
} 

static void f1(void) { 
    printf("f1 address: %d\n", f1); 
    pid_t pid; 

    if ((pid = vfork()) < 0) 
     err_sys("vfork error"); 
} 

static void f2(void) { 
    printf("f2 address: %d\n", f2); 
    char buf[1000]; 
    int i; 

    for (i = 0; i < sizeof(buf); ++i) 
     buf[i] = 0; 
} 

я запустить программу, вывод:

main address: 4196560 
f1 address: 4196604 
f2 address: 4196663 
f1 address: 4196604 
[1] 12929 segmentation fault ./a.out 

Я смущен о выходе.

  1. print f1 address: xxx, мы вызываем vfork(), сначала выполняется дочерний процесс.
  2. печать f2 address: xxx, затем дочерние процессы вызывает _exit (0).
  3. основной прогресс возвращается из f1(), кадр стека f1 был изменен на f2, это может привести к ошибке сегментации.

Но зачем печатать f1 address: 4196604 дважды и почему адрес f1 и f2 не одинаковый?

+0

'buf' не инициализируется так' STRLEN (ЬиЕ) 'не определено поведение (и, вероятно, причиной Segfault). Это было намеренно? – rici

+0

является vfork псевдоним fork() на вашей платформе? – hd1

+0

@rici sizeof (buf) то же самое –

ответ

0

Я не уверен, что вы подразумеваете под «рамкой statck из f1 был изменен на f2».

Код в f2(), скорее всего, будет иметь дефект сегментации в любом случае, независимо от vfork(). buf неинициализирован. Нет причин полагать, что он содержит строку с нулевым завершением. Поэтому вызов strlen() может считывать конец буфера.

В любом случае, я не уверен, что вы ожидаете от цикла. В первой итерации i равен 0. Если вызов strlen() не выполняется, тогда тело цикла сохраняет 0 в buf[0]. Поэтому на следующей итерации цикла strlen(buf) будет 0, i будет 1 (что не менее 0), поэтому цикл завершится.

Второй отпечаток f1 address: 4196604 - это когда родительский процесс продолжается после завершения подпроцесса vfork(). Родительский процесс продолжается и вызывает f1(), который печатает это.

Номера, которые вы печатаете, являются адресами f1 и f2. Почему вы ожидаете, что адрес f1 будет таким же, как адрес f2? Их нет, поэтому они печатают разные адреса.

С другой стороны, адрес f1 является таким же в родительском процессе и подпроцессе, поскольку подпроцесс разделяет адресное пространство родителя. Таким образом, тот же адрес печатается для f1 оба раза.

+0

Я изменяю strlen() с sizeof(). Код представляет собой упражнение «Расширенное программирование в среде UNIX Environmnet». –

+0

И, сделав это изменение, он все еще неисправен? –

+0

Я обновляю вопрос, и вы можете посмотреть. После изменения он все еще не выполняет сегментацию. –

0

Согласно vforkdocumentation, вы не должны возвращаться от текущей функции.

vfork() отличается от вилки (2) в том, что вызывающий поток приостанавливается , пока ребенок не прекращает (либо нормально, позвонив по телефону _exit (2), или аномально, после доставки фатального сигнала), или он звонит execve (2). До этого момента ребенок делит всю память с ее родителем , включая стек. Ребенок не должен возвращаться из текущей функции или вызова (3), но может вызывать _exit (2).

Кроме того, обратите внимание, что:

vfork() представляет собой частный случай клона (2). Это , используемые для создания новых процессов без копирования таблиц страниц родительского процесса. Он может быть полезен в приложениях с высокой степенью чувствительности, где создается дочерний элемент , который затем немедленно выдает execve (2).

С vfork не копирует таблицы страниц из родителя, имеет смысл не возвращаться от текущей функции. Когда ребенок выйдет, это испортит кадр стека из родителя.

Вы также можете просмотреть following answer

 Смежные вопросы

  • Нет связанных вопросов^_^