Как стать автором
Поиск
Написать публикацию
Обновить

Программирование на C в Linux на примере создания командной оболочки: часть 2

Уровень сложностиСредний
Время на прочтение55 мин
Количество просмотров10K
Всего голосов 24: ↑23 и ↓1+30
Комментарии12

Комментарии 12

Я что-то пропустил или раскрытия wildcard'ов пока нет?

К сожалению пока фильтры отбора не реализовал. Но кстати, я совсем забыл о них. Благодарю.

Не вижу как создать новый комментарий, поэтому напишу тут.

1) Каждый модуль должен иметь свой заголовочный файл.

2) Все функции и переменные должны быть либо static либо присутствовать как extern в заголовочном файле

3) Разделение на каталоги src и include на мой взгляд неразумно и неудобно

Впечатление от Вашей деятельности двоякое:

С одной стороны - Отлично, что человек изучает такой базовый язык и делает интересную задачу.

С другой стороны - базовый язык немножко требует аккуратности. И с учётом того, что пишете Вы не "hello world", а шелл, то возможно к этому нужно больше внимания.

Чтобы не быть голословным (возможно, для Вас это очевидно, но ... ) на всякий случай обозначу:

char *data = malloc(sizeof(char) * 256);

...

strcpy(data, line);

Во-первых, лучше проверять результат, возвращаемый функциями. И к malloc это относится особенно. Рассказы про то, что отсутствие памяти автоматически означает что всё плохо - это всё для детского сада. Ограничений может быть много, они могут быть временными.

-

Во-вторых, есть некоторое ... заблуждение, что ли? про размер базовых типов:

То, что char может занимать больше одного байта это Вы правильно подметили, однако это такой общий костыль для решения аппаратно-платформенных проблем. Это не решения для языка C. В частности, если посмотреть сюда:

https://en.cppreference.com/w/c/language/sizeof

то там явно написано что sizeof(char) всегда возвращает 1, даже если размером он больше 8 бит:

sizeof(char), sizeof(signed char), and sizeof(unsigned char) always return 1

Т.е. все Ваши приседания с попытками угадать размеры - они излишни. Тут нужно быть совсем поаккуратнее.

-

Ну и на закуску немного про логику:

while (fgets(line, sizeof(line), file)) - нарежет длинную строку из файла на кусочки по 255 байт (длина line - 1). Соответственно, очень длинная строка может превратиться в 5, или 10, или ещё во что-то.

Прим.: разбор текстов у Вас, по-моему, вообще очень смелый.

-

Также:

progs = realloc(progs, capacity * sizeof(char *));
if (progs == NULL) {
fprintf(stderr, "Ошибка выделения памяти: %s\n", strerror(errno));

Насколько помню API, когда realloc возвращает NULL, то errno не меняется. Т.е. Вы получите либо "Всё ОК", либо описание какой-то более ранней ошибки.

Резюмируя:

Читайте стандарт, читайте стандартную библиотеку. И будет Вам счастье.

Дополнение: разбивка строк на абстрактные кусочки ещё плоха тем, что многобайтный символ (например, русская буква в UTF8 или китайские иероглифы) может развалиться на две части (это уже плохо) и один из образовавшихся кусков текста может стать невалидной строкой (это очень плохо).

Огромное спасибо вам, буду исправлять.

Во-первых, лучше проверять результат, возвращаемый функциями. И к malloc это относится особенно.

Кстати, подскажите, как без модификации системных настроек получить 0 от malloc, выделяя память мелкими кусками. У меня на синтетических тестах не получилось, OOM killer приходил раньше.

Согласен, что думать об этом в принципе надо, но вариант "в текущем проекте мы не проверяем ошибки выделения памяти потому что 1) ... 2) ..." (чётко прописанный рядом с coding guidelines и прочими документами) имеет право на жизнь. И я бы хотел посмотреть на более менее сложный продукт, адекватно обрабатывающий исчерпание системной памяти (учитывая, например, что реальное выделение может случится при первом обращении к странице в произвольном коде). Если хочется полной стабильности, надо жить в своём хипе, запрашивая память у системы только на старте.

Уважаемый автор и комментаторы-знатоки - можете посоветовать, что нужно поучить дополнительно, чтобы лучше погрузиться в мир С?

Поясню. Я в этом году учил Python. Больше было теории - прошел небольшой курс, задачки по нему решал, книгу параллельно читал, Ютуб (по ООП на питоне). Но когда я захотел что-то сам написать, оказалось, что ничего особо и не могу (с нуля). Кроме простых задач. Все что сложнее - требовало знаний библиотек, фреймворков. А ещё - знание по устройству ОС, баз данных (причем недостаточно sql изучить, надо ещё и orm, типа алхимии), сетей ( и библиотек для работы с ней) и т.д. Даже банально залить на линуксовый сервак простенький скрипт - было нетривиальной задачкой. Ведь это работа с незнакомой ос через консоль по сети. Что вскрывает ещё целый пласт необходимых к изучению знаний.

Я был очень демотивирован - эта кроличья нора казалась бездонной. Да и сейчас такой ощущается. И мне посоветовали выучить С, сказали, что в процессе изучения этого языка ты одновременно изучаешь и строение ОС и работу компьютера и много чего еще. Верно ли это? Или тут тоже надо дополнительно что-то изучить, чтобы не повторить печальный опыт с python?

Конечно, у меня есть понимание, что книги по сетям, ОС и т.п. все равно надо прочесть. Но хотелось бы делать эта не в отрыве, а более органично. Не так, чтобы прочитать про модель OSI и потом такой: "И...? Как это использовать? Как совместить с программированием? Сетевой протокол? Как он выглядит? Как его написать самому? Как использовать существующий протокол на практической реальной задачке? Пример такой задачи."

Но если это мое желание нереалистичное - то прошу так и написать. Будет проще сориентироваться, что делать дальше.

Благодарю за внимание!

Все что сложнее - требовало знаний библиотек, фреймворков. А ещё - знание по устройству ОС, баз данных

У вас уже есть хороший список того, что нужно подтянуть. Зачем при этом менять язык программирования? Просто чтобы превозмогать?

Кроме языка сосредоточтесь на структурах данных, это точно не будет бесполезным.

Довольно непонятный вопрос. Вы сами-то чего хотите? Какая у вас цель?

Хороший вопрос. На некоторые вопросы трудно ответить, находясь в текущей фазе. В школе дети часто не понимают, зачем им изучать какой-то предмет. И они правы. Не нужно. Но это актуально только в тот момент, когда они задаются этим вопросом. Через 5 лет или 15 - ситуация может измениться. И тот же человек будет думать - почему он не изучил это раньше? Поэтому я не могу ответить на ваш вопрос. Мои текущие интересы временны и преходящи.

Но вот что я хорошо понимаю, что знания это как айсберг. Для жизни может хватить самых минимальных знаний (с верхушки). И если твой айсберг - это плоская льдина, то тебя будет болтать туда-сюда по океану жизни. Причем льдина будет трескаться, ломаться, отрастать вновь. Льдина - это наши знания и опыт. Они растут как в глубину (качественно), так и в ширину (количественно). Рост неравномерный. Поэтому старый человек - это не равно "мудрый".

Для работы и жизни мне хватает своих знаний и опыта. Но порой, я остро чувствую, что мой айсберг в каких-то моментах - это тонкая льдина. Это нормально. Но чувство мерзкое. Поэтому, если изучать программирование, то лучше на достаточно глубоком уровне. В противном случае - зачем вообще кодить? Ведь low-code разработчики тоже себя программистами называют)

P.s. сорри за эту портянку текста. Само получилось.

Если вы хотите достичь ощущения, что всё знаете и понимаете в программировании и работе компьютера, то можете не мучать себя понапрасну, этого ощущения не будет никогда.

(вообще, психологические состояния достигаются психологическими же практиками, а не какими-то внешними факторами)

если изучать программирование, то лучше на достаточно глубоком уровне

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

Знания, которые человек получает просто чтоб были, лежат у него в голове мёртвым грузом и быстро вымываются. Повторять ненужные знания, чтобы удержать их в голове непонятно зачем - это совсем уж безумие.

Знания впору, когда они выцепляются конкретными задачами. Если вы, будучи программистом высокого уровня, не испытываете практической надобности в изучении нижележащих слоёв, то это значит лишь, что слои абстракций хорошо построены и вам не о чем беспокоиться.

Если же вы непременно хотите освоить низкие уровни просто из любви к искусству, то ок, но всё равно нужно поставить какую-то задачу, иначе это будет блуждание в хаосе. Попробуйте, например, написать какой-нибудь прикольный модуль для ядра Linux - свою файловую систему, например. Или ещё что-то в этом роде. Эта задача потянет за собой целые пласты знаний.

Спасибо за совет! Вы скорее всего правы.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий