Понимание поведения read () и write () - PullRequest
3 голосов
/ 04 июня 2010

привет, я студент и только начал изучать программирование на низком уровне c. Я пытался понять методы read() и write() с помощью этой программы.

#include <unistd.h>
#include <stdlib.h>
main()
{
    char *st;
    st=calloc(sizeof(char),2);//allocate memory for 2 char
    read(0,st,2);
    write(1,st,2);
}

Я ожидал, что это вызовет ошибку сегментации, когда я попытаюсь ввести более 2-х символов ввода. Но когда я выполняю программу и вводлю asdf после того, как в качестве вывода она выдает, она выполняет команду df. *

Я хочу знать, почему он не дает ошибки сегментации, когда мы присваиваем более 2 символов для строки размером 2. и почему он выполняет остаток (после 2 символов) ввода как команду вместо того, чтобы выдавать ее как выход только

также чтение man-страницы read (), которую я нашел read (), должно выдавать ошибку EFAULT, но это не так.

Я использую Linux.

Ответы [ 5 ]

3 голосов
/ 04 июня 2010

Ваш read определенно заявляет, что ему нужны только два символа, так что это все, что он получает. Вы не вводите больше символов в область st, чтобы не допустить нарушений сегментации.

Что касается того, почему он выполняет часть df, то на самом деле это не происходит в моей непосредственной системе, так как программа зависает до нажатия клавиши ENTER, и кажется, что ввод-вывод программы поглощает дополнительное. Но эта непосредственная система - Cygwin - см. Обновление ниже, чтобы узнать о поведении в «реальном» окне UNIX.

И вы получите EFAULT только если st находится за пределами вашего адресного пространства или иным образом недействителен. Это не тот случай.


Обновление:

Пробуя это в Ubuntu 9, я вижу, что поведение идентично вашему. Когда я добавляю символы asls, программа выводит as, затем выводит список каталогов

Это означает, что ваша программа читает только два символа, а оставшаяся остается для чтения следующей программы, которая является оболочкой.

Только убедитесь, что вы не пытаетесь ввести:

asrm -rf /

(нет, серьезно, не не делайте этого).

2 голосов
/ 04 июня 2010

Вы просите read() прочитать не более 2 символов (третьи параметры - read()), и поэтому он заменяет не более двух символов в указанном вами буфере. Вот почему нет никаких причин для ошибочного поведения.

1 голос
/ 04 июня 2010

Когда вы читаете (), вы указываете, сколько байтов вы хотите. Вы не получите больше этого, если ваш libc не сломан, поэтому вы никогда не будете писать за пределами вашего буфера, пока ваш счетчик никогда не будет больше, чем размер вашего буфера. Дополнительные байты остаются в потоке, и следующее чтение () получит их. И если у вас нет следующего read () в вашем приложении, процесс, который его породил (обычно это оболочка), может их увидеть, так как порождение консольного приложения из оболочки включает в себя присоединение входных и выходных потоков оболочки к процесс. То, увидит ли и получит ли оболочка байты, отчасти зависит от того, сколько буферизации выполняется за кулисами libc, и может ли она «разблокировать» любые буферизованные байты при выходе.

0 голосов
/ 04 июня 2010

Поскольку вы читаете только 2 символа, проблем нет. символы df не потребляются вашей программой, поэтому они остаются в буфере терминала и используются оболочкой:

  • ваша программа работает
  • вы вводите asdf\n
  • ваша программа читает as и оставляет df\n в буфере tty
  • вы записываете содержимое буфера st в stdout
  • ваша программа останавливается
  • оболочка читает df\n из ввода и выполняет команду df.

Забавные вещи, которые стоит попробовать:

  • связать вашу программу, чтобы отследить системный вызов: strace -e read, write ./yourprogram
  • read(0, st, 5)
0 голосов
/ 04 июня 2010

с чтением (0, ст, 2); Вы читаете 2 символа из стандартного ввода. Остальная часть введенного вами текста не будет извлечена из программы, но не будет опущена, поэтому нажатия клавиш возвращаются в оболочку, из которой запущена ваша программа (которые представляют собой df и enter).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...