Основы программирования для Linux

1.1 Основной инструментарий разработчика Linux

Установка набора компиляторов GCC, утилиты make и текстового редактора Vim:
$ sudo apt-get install git
$ gcc --version
$ make --version

Для того чтобы сделать Vim красивым надо отредактировать его rc-файл:
$ vim ~/.vimrc

set number
colorscheme darkblue

Для сохранения конфигурации надо дать команду :wq.

Компиляция программы в простой исполняемый файл:
$ gcc -o hello main.c

В Linux текущий каталог не входит в набор для поиска путей программ, поэтому требуется вводить ./, например ./hello.

1.2 Динамические библиотеки и линковка

Для того чтобы в окне Vim открыть второй файл надо дать команду :sp . и выбрать файл. Окно Vim разделится на две части. Третий файл можно открыть командой :vs . при этом верхняя часть окна разделится на две части.

Для создания пустого файла в Linux используется команда touch.

Ключик -c говорит gcc выполнить только этап компиляции, без линковки.
$ gcc -o hello.o -c hello.c
$ gcc -o main.o -c main.c

Для просмотра списка файлов используется команда ll.

Линковка в единый исполняемый модуль:
$ gcc -o hello hello.o main.o

Компиляция разделяемой библиотеки:
$ gcc -o libHello.so -shared -fPIC hello.c

Имена (символы), которые библиотека экспортирует и импортирует:
$ nm libHello.so
$ man nm

Получение программы, которая использует динамическую библиотеку:
$ gcc main.c -L. -lHello -o hello

Ответственным объектом по поиску динамических библиотек является системный сервис ld.
$ export LD_LIBRARY_PATH=.
$ ./hello 

Утилитой c++filt можно расшифровать С++ имя после манглинга. Отключить манглинг для C++ можно следующим образом:
#ifndef __HELLO__
#define __HELLO__
extern "C" void hello_message(const char *name);
#endif

Утилита make - это утилита для управления зависимостями.

Цели buildall и clean:

$ vim Makefile
$ make
$ make clean
$ make lib

Библиотеки, которые использует модуль:
$ ldd hello
$ ldd libHello.so

1.3 Runtime линковка. Libdl

В ряде случаев требуется линковать библиотеки прямо в runtime. Схема динамической линковки в runtime:

Makefile
main.c

LD_LIBRARY_PATH позволяет указать, где dlopen будет искать библиотеки.
Программист должен вручную привести указатель возвращаемый dlsym к типу вызываемой функции.

1.4 Обработка параметров командной строки. Getopt 

$ man 3 getopt

Опция может иметь длинную и короткую форму.
Опции могут иметь собственные аргументы.
Каждая пара опций командной строки (короткая версия, длинная версия) описывается структурой option.



3.1 Базовые функции работы с файлами

Файл – это именованная последовательность байт на жестком диске. Все файлы связаны иерархической системой имен, начинающейся с символа /. Файлу сопоставлен набор атрибутов, таких как имя, время доступа к файлу, размер... 

Файл - это еще и системный интерфейс.

Функции, которые относятся к системному интерфейсу доступа к файлам в Linux:
  • ssize_t write(int fd, const void *buf, size_t count)
  • int open(const char *pathname, int flags);
  • ...

Все системные вызовы описаны во втором наборе man-страниц.
Флажки при открытии файла: O_RDONLY, O_WRONLY, O_RDWR.

$ man 2 open


  • O_CREAT - Файл будет создан при открытии, если не существует, при наличии соответствующих прав.
  • O_APPEND - Режим добавления. Перед каждым вызовом write указатель на текущую позицию будет перемещен в конец файла.
  • O_RDONLY - Файл в режиме только для чтения.
  • O_TRUNC - Если файл существует, то при открытии его содержимое будет удалено.
  • O_RDWR - Файл открывается для чтения и записи.

3.2 Работа с каталогами и путями


3.3 Ссылки

$ touch test
$ vim test
$ stat test
$ ln test test.hardlink
$ stat test.hardlink
$ ln -s test.softlink
$ stat test.softlink
$ rm test
$ cat test.softlink
$ cat test.softlink



Если мы не хотим открывать ссылки, то это делается с помощью флажка O_NOFOLLOW.


С помощью флажка O_PATH можно открыть файл символической ссылки.


3.4 Файловая система /proc. Построение дерева процессов

Для того чтобы обнаружить какие вызовы выполняет приложение и какие системные вызовы выполняет приложение в нашем распоряжении есть две утилиты:
$ man ltrace
$ man strace


Как использовать файловый интерфейс для того чтобы обращаться в память ядра:


Команда mount выводит все точки форматирования.
Команда echo $$ выводит идентификатор нашего процесса.

Текущий каталог нашего процесса:
$ ls -la /proc/25040/cwd

  • environ - переменные окружения;
  • limits - ограничения, которые заданы процессу;
  • ns - информация о пространствах имен;
  • status - статистика.

Информация о процессорах:
$ cat /proc/cpuinfo |less

4.1 Жизненный цикл процесса в Linux

Дерево процессов:
$ pstree -p

Понятия, которые могут принадлежать процессу или являться его атрибутами:
  •  пространство файловых имен
  •  Состояние регистров
  •  Память (адресное пространство)
  •  Полномочия (credentials)
  •  Код возврата
  •  PID

4.2 Создание процессов fork/exec

Механизмы создания процессов:

fork:

exec:
$ man 2 execve

Схема создания нового процесса:

  • fork может быть использован без exec, если код потомка содержится в том же бинарном файле что и код родителя.
  • exec замещает текущую память процесса новым образом.
  • fork копирует текущий процесс, таким образом, что состояние памяти оказывается одинаковым у родителя и потомка.

$ man 2 wait

  • Семейство функций wait позволяет дождаться изменения состояния процесса-потомка.
  • Если родитель не запросил код возврата у завершенного процесса-потомка, то он превращается в "зомби".
  • wait является синхронной и блокирует процесс, который ее вызвал.

4.3 Атрибуты создаваемого процесса. Системный вызов clone


В Linux процесс рассматривается как единица планирования.

Демонстрация вызова clone:

Флажок CLONE_PARENT:

4.4 Процессы-демоны


5.1 Виды межпроцессного взаимодействия в Linux


  • Файлы, содержащие 1 байт и 20 байт будут иметь при хранении на диске один и тот же размер.
  • Каждая файловая система предлагает свой набор атрибутов файла.
  • Разные приложения могут читать из одного и того же файла не заботясь о синхронизации.

5.2 Каналы


$ man pipe
$ man popen
$ man 3 mkfifo

5.3 Сигналы


$ man kill

Список сигналов:
$ kill -l

$ man 2 kill


5.4 Разделяемая память


Список регионов shared memory:
$ ipcs -m

5.5 Мультиплексирование ввода-вывода