Как создать свою оболочку для linux

Обновлено: 03.07.2024

В этой статье мы поговорим о создании графического интерфейса для вашей Linux-программы. Как вы знаете, средствами одного С нормальный GUI (Graphical User Interface – Графический интерфейс пользователя, ГИП) не построишь, тем более что после Windows пользователь очень требователен не только к наличию этого самого GUI, но еще и к дизайну формы (окна программы). Поэтому без дополнительных библиотек вам не обойтись. Самыми распространенными библиотеками для создания GUI являются библиотеки GTK и Qt. Рекомендуется использовать только эти библиотеки, поскольку велика вероятность того, что они уже будут установлены у пользователя (уж GNOME и KDE установлены почти у всех), чтобы не сложилась такая ситуация, когда размер вашей программы 300К, а используемая нею библиотека «весит» 20М. Вот подумайте, зачем пользователю ваша программа и станет ли он закачивать ее из сети? Конечно, если для вашего шедевра нет аналогов в мире, вы можете изрядно поиздеваться над пользователем, используя нестандартную библиотеку GUI. В первой части этой статьи будет рассмотрена библиотека GTK, а во второй – Qt. Сразу следует заметить, что эта статья – не русскоязычное руководство по библиотекам GTK и Qt. Это, скорее, небольшой обзор возможностей библиотек.

Скорее всего, GTK уже будет у вас установлена, но вам нужно будет установить пакет gtk+-devel, содержащий необходимые файлы для разработки GTK-программ.

Не хочется в этой статье рассматривать банальный пример окошка с кнопкой hello world!. Уж слишком уж это просто, да и этот пример вы сможете найти в документации по Gtk.

Сейчас напишем небольшой конфигуратор, который будет вносить изменения в файл /etc/resolv.conf. Напомню вам формат этого файла:

Директива domain определяет наш домен, а две директивы nameserver – первый и второй DNS-серверы, соответственно. Вместо директивы domain можно использовать директиву search, но это кому как нравится. Файл может содержать до 4 директив nameserver, но обычно указываются только два сервера DNS, поэтому мы не будем перегружать себя лишней работой. Но файл resolv.conf не главное в нашей статье – ведь мы разрабатываем GUI. Наш конфигуратор не будет вносить изменения в настоящий файл /etc/resolv.conf – для этого нужны права root, можно, конечно, вызвать auth для аутентификации, но мы не будем этого делать, чтобы не усложнять код программы.

Теперь небольшое вступление в GTK. Элементы ГИП – кнопки, поля ввода, переключатели и тому подобное называется виджитами. Если вы когда-нибудь работали в Delphi, виджиты подобны визуальным компонентам Delphi.

Как и в Delphi, основным элементом GUI является окно (форма в Delphi). Виджиты для размещения в окне помещаются в контейнер. В самом окне выравнивать виджиты можно с помощью вертикальных/горизонтальных боксов или же таблиц. Мне больше нравится второй способ, поэтому мы будем использовать именно таблицы.

Виджиты могут реагировать на сигналы, например, щелчок мышью. При этом вызывается функция-обработчик события (сигнала), если вы определили ее.

В качестве примера нарисуем кнопку и определим обработчик ее нажатия:

А вот функция hello():

Хватит теории, перейдем к практике. На рисунке 1 изображена уже готовая программа. Работает она так. Когда пользователь введет что-нибудь в поле ввода и нажмет Enter, программа отобразит введенный им текст на консоли. Когда пользователь нажмет Ок, введенная им информация будет еще раз выведена на консоль и записана в файл. При нажатии кнопки Quit программа завершит свою работу. Она должна также завершить работу при нажатии кнопки закрытия окна – в GTK программист сам определяет реакции на стандартные кнопки.

Вот текст программы. Внимательно читайте комментарии.

Я старался писать подробные комментарии, но все же кое-что осталось в тумане. Это координаты ячеек. Рассмотрим нашу таблицу 3х3:

Сначала указываются координаты по X, затем – по Y. Вот координаты кнопки Ok: 2,3,0,1. Это означает, что кнопка будет расположена в последнем столбике (2,3), но в первом ряду (0,1). Чтобы было понятнее: ОК по Х находится между 2 и 3, а по Y – между 0 и 1.

Теперь откомпилируем нашу программу:

У вас некорректно отображаются русские названия надписей и кнопок? Эта проблема очень быстро устраняется с помощью GNOME Control Center – вам всего лишь нужно выбрать другой шрифт.

Настоящая статья является дополнением к книге «Инструменты Linux для Windows-программистов». Это не описание как делать GUI приложения в Linux, это описание того, как ПРИСТУПИТЬ к созданию графических приложений в Linux, и, хотелось бы надеяться что это прозвучит - чем принципиально программирование графики в Linux отличается от того же занятия в Windows. Главным требованием здесь была простота. Сделав простейший шаблон GUI прложения, дальше двигаться уже гораздо проще. Кроме того, все эти простейшие приёмы программирования показаны сравнительно: на основе основных графических технологий (библиотек), используемых в UNIX.

Все примеры к тексту вы можете скачать в виде общего архива.

Создание приложений, взаимодействующих с пользователем посредством графического интерфейса (GUI приложений), является частным классом задач, отдельной областью программирования. Из числа других подобных областей приложения можно было бы привести, как примеры:

  • реализация алгоритмов цифровой обработки сигналов (DSP): быстрые спектральные преобразования (FFT и другие), вэйвлеты, авторегрессионные разложения. ;
  • обработка аудио-потоков (пакеты: sox, ogg, speex и другие);
  • задачи IP-телефонии, SIP протокола, реализация разнообразных программных SoftSwitch;

Это сравнительный ряд автономных областей развития приведен как пример таких частных классов, одним из которых является и разработка GUI приложений. И как частный класс, со своей спецификой инструментов и средств, он не заслуживал бы отдельного упоминания, если бы не одно обстоятельство — принципиально отличающееся, диаметрально противоположное отношение к GUI в операционных системах семейства Windows и в UNIX (и в Linux, как его частный вид):

  • В Windows каждое приложение является принципиально GUI, неотъемлемым атрибутом любого приложения в Win32 API (низкого уровня) является главное окно приложения, уже само приложение «вяжется» вокруг его главного окна. Операционная система регистрирует классы окон и уже далее к ним соотносит конкретные приложения. Не может существовать приложения (взаимодействующего с пользователем, не системные службы) без окна, с этим были связаны и первоначальные сложности Windows в реализации консольных (терминальных) приложений.
  • в UNIX картина принципиально обратная: первичным является приложение, которое, по умолчанию, является консольным, текстовым, вся графическая система не является составной частью операционной системы, а является надстройкой пользовательского уровня. Чаще всего такой графической надстройкой является X11 (в реализации Xorg или X11R5), но и это не обязательно: практиковались и другие графические системы, хороший пример тому графические системы Qwindow, а затем Photon в операционной системе QNX, сосуществующие там одновременно с X11.
  • Показательно в этом смысле то, что вся оригинальная часть реализации X11 работает в пространстве пользователя, не в привилегированном режиме ядра (супервизора): работа с аппаратурой видеоадаптеров, устройствами ввода и другое. Отдельные реализации (видеосистемы NVIDIA или ATI Radeon) могут быть реализованы в режиме ядра (модули), но это а) сторонние относительно X11 разработки, и б) решение вопросов только производительности.

Из-за обозначенной специфики, разработка GUI приложений в UNIX (Linux) принципиально отличается:

  • вся работа GUI приложений ведётся через промежуточные слои (библиотеки) пользовательского уровня;
  • из-за того, что это ординарный пользовательский уровень, для разработчика предлагается широкий спектр альтернативных инструментов (библиотек), практически равнозначных, и конкурирующих друг с другом: Xlib, GTK+, Qt, wxWorks и многие другие.
  • базовый API работы с X11 предоставляет Xlib, все другие используют уже её функционал, как это показано на рисунке.


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

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

Средства Xlib (архив Xlib.tgz ):



Средства GTK+ (архив GTK+.tgz ):

$ gcc gtk.c -o gtk `pkg-config --cflags --libs gtk+-2.0`



Средства Qt (архив Qt.tgz ):

Средства Qt предполагают написание приложений на языке С++, и имеют развитый инструментарий, в частности, построения сценария сборки приложения. Создадим в рабочем каталоге (изначально пустом) файл исходного кода приложения с произвольным именем:

Теперь проделываем последовательно:

Исходя из «подручных» файлов исходных кодов, у нас сгенерировался файл проекта и, далее, сценарий сборки ( Makefile ). Далее проделываем традиционную сборку, а заодно и посмотрим опции компиляции и сборки, которые нам сгенерировал проект:

g++ -c -pipe -Wall -W -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables

g++ -o Qt index.o -L/usr/lib/qt-3.3/lib -lqt-mt -lXext -lX11 -lm

index.cc index.o Makefile Qt Qt.pro



Средства wxWidgets (архив wxWidgets.tgz):

simple.cc :

$ g++ simple.cc `wx-config —cxxflags` `wx-config --libs` -o simple



Средства GLUT (архив glut.tgz):

OpenGL Utility Toolkit, как и следует из названия, это средства использования технологии OpenGL в приложениях, которая требует определённой поддержки со стороны видео оборудования.

$ gcc glut.c -o glut -lX11 -lglut



То, что показано выше, это фактически не приложения, а скелеты приложений, но они позволяют: а) сравнить подобие всех GUI технологий в X11, и б) быть отправной точкой для сборки более содержательных GUI приложений. Показано только несколько GUI технологий, применяемых в X11 (большинство из них являются кросс-платформенными, и применимы в большинстве существующих операционных систем). Каждая из этих технологий, а названы только немногие из значительно большего числа, присутствующих в UNIX, могут быть полной альтернативой любой другой из этого же ряда, они взаимно заменимы, и даже взаимно дополняемые.

В данной статье были показаны образцы кода GUI приложений. Естественно, визуальные образы таких приложений строятся не путём непосредственного кодирования, а при использовании некоторых визуальных построителей, в составе тех или иных интегрированных средств разработки (IDE).

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

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

Для начала пара слов о том, из каких компонентов состоит то, что мы называем рабочим столом. Базовый функционал работы с окнами (и не только, но сейчас это не важно) предоставляет X server или идущий ему на смену Wayland . Он непосредственно взаимодействует с аппаратной частью (видеокартой) через соответствующие модули (или драйвера). Поверх него работает менеджер окон. От этого компонента зависит то, как будут выглядеть сами окна, их границы, заголовки и декорации. Следующий компонент - композитный менеджер. Он отвечает за прозрачность и тени. Все элементы рабочего стола являются приложениями, запущенными в собственных окнах но не обычных, а с определенными атрибутами. И это логично. Ну зачем, скажите, какой-то панели, виджету или доку нужны декорации окна? Да, вы сделали правильный вывод, окна бывают разные ;-)

Все компоненты могут иметь очень разные возможности и, в следствии этого, отличаются аппетитом к ресурсам компьютера, в частности к количеству памяти, производительности процессора и видеокарты. Также на их аппетит влияет включение и выключение различных функций.

Итак, первым в нашем творении компонентом будет менеджер окон. Одним из самых лёгких и гибких в настройке является OpenBox . Его мы и будем использовать. Не важно какой дистрибутив Linux вы используете, вы можете установить несколько различных менеджеров окон. Для Debian - подобных дистрибутивов для установки OpenBox выполним команду:

sudo apt install openbox

Далее делаем logout из вашего текущего окружения, в меню приветствия вводим логин с паролем и выбираем тип сессии openbox .

Что мы видим? Да, серый экран и ничего более. Тем не менее этим сверхминималистичным окружением уже можно пользоваться. Нажимаем правую кнопку мышки в любом месте экрана и видим меню с базовым набором пунктов. Находим в этом меню терминал и запускаем. Отлично, теперь у нас есть нужный инструмент. Для удобства работы в терминале я использую консольный файловый менеджер Midnight Commander, что и вам рекомендую. Установить его можно командой

Всем привет! Хочу поделиться своим опытом написания собственной командной оболочки Linux используя Posix API, усаживайтесь поудобнее.

Что должна уметь наша командная оболочка

Запуск процессов в foreground и background режиме

Завершение background процессов

Поддержка перемещения по директориям

Как устроена работа командной оболочки

Считывание строки из стандартного потока ввода

Разбиение строки на токены

Создание дочернего процесса с помощью системного вызова fork

Замена дочернего процесса на необходимый с помощью системного вызова exec

Ожидание завершения дочернего процесса (в случае foreground процесса)

Немного про системный вызов fork()

Простыми словами системный вызов fork создает полный клон текущего процесса, отличаются они лишь своим идентификатором, т. е. pid .

Что выведет данная программа:

I'm parent process!
I'm child process!

Что же произошло? Системный вызов fork создал клон процесса, т. е. теперь мы имеем родительский и дочерний процесс.

Чтобы отличить дочерний процесс от родительского в коде достаточно сделать проверку. Если результат функции fork равен 0 - мы имеем дело с дочерним процессом, если нет - с родительским. Это не означает, что в операционной системе id дочернего процесса равен 0 .

Причем, порядок выполнения дочернего и родительского процесса ничем не задекларирован. Все будет зависеть от планировщика операционной системы. Поэтому в конце блока родительского процесса добавлена строчка wait(NULL) , которая дожидается окончания дочернего процесса.

Подробнее про exec()

В документации есть различные вариации системного вызова exec , но они отличаются только способом передачи токенов в параметры функции, смысл от этого не изменяется.

Системный вызов exec заменяет текущий процесс сторонним. Естественно, сторонний процесс задается через параметры функции.

Что выведет данная программа

total 16
-rwxr-xr-x 1 runner runner 8456 Jan 13 07:33 main
-rw-r--r-- 1 runner runner 267 Jan 13 07:33 main.c

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

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

Перейдем к полноценной реализации

Часть 1. Чтение строки с консоли

Изначально нам надо уметь считывать строку из командной строки. Думаю, с этим не возникнет сложностей.

В данной функции происходит чтение строки с применением функции getline . После чего, если в конце строки имеется символ переноса строки, удаляем его.

Обратите внимание, что при чтении могут возникнуть ошибки, одна из них - нажатие сочетания клавиш ctrl-D . Однако это штатный случай завершения работы командной оболочки, следовательно в данном случае не должна выводиться ошибка.

Часть 2. Разбиение строки на токены

В данной части будет представлена реализация разбиения строки на массив токенов.

Определения начальной длины массива и разделителей строки.

Код выглядит довольно громоздким, однако в нем нет ничего сложного.

Очередной токен получается с использованием функции strtok . После чего данный токен копируется в массив токенов. Если в массиве токенов не достаточно места, массив увеличивается в 2 раза.

Завершается всё добавлением завершающего токена равного NULL , т. к. функция exec() ожидает наличие данного завершающего токена.

Часть 3. Выполнение процессов

Структура хранения списка запущенных процессов

Напишем определения структур для foreground и background процессов, fg_task и bg_task . А также определение структуры для хранения всех процессов tasks .

Создадим в коде глобальную переменную типа tasks , которая и будет хранить все наши запущенные процессы.

Вспомогательные функции добавления процессов

Установка foreground процесса выглядит банально и не нуждается в комментировании.

Добавление background процесса выглядит посложнее.

На деле же все проще. Смотрим есть ли место в массиве для хранения информации о процессе. Если его недостаточно - увеличиваем длину массива в 2 раза. После чего происходит добавление структуры bg_task в массив и последующее заполнение полей структуры информацией о процессе.

Данная функция возвращает -1 в случае неудачи.

Вспомогательные функции для завершения процессов

Добавим функцию экстренного завершения foreground процесса. Данная функция с помощью системного вызова kill с параметром SIGTERM завершает процесс по id процесса.

Также добавим функцию для завершения background процесса.

Данная функция принимает в себя массив токенов вида ", NULL> . После чего преобразует токен индекса background задачи в число. Убивает background задачу посредством системного вызова kill .

Непосредственно запуск процессов

Для удобства введем функцию is_background , определяющую является ли задача фоновым процессом. Данная функция просто проверяет наличие & в конце.

Введем функцию launch которая будет запускать background процесс если в конце присутствует токен & , иначе будет запускаться foreground процесс.

То, что происходит в этой функции уже должно быть все понятно.

Создается дубликат процесса с помощью системного вызова fork

Заменяем дочерний процесс на требуемый с помощью системного вызова exec

Определяем является ли процесс фоновым

Если процесс фоновый - просто добавляем его в список bacground задач

Если процесс не фоновый - дожидаемся окончания выполнения процесса

В функции присутствует неизвестная функция quit . Ее мы разберем в следующем блоке.

Вспомогательные функции для командной оболочки.

Введем функцию execute , которая в зависимости от первого токена выбирает нужное действие.

Данная функция пропускает действие, если первый токен NULL . Смена директории, если первый токен cd . Вывод справки об использовании, если первый токен help . Завершение работы командной оболочки, если первый токен quit . Вывод списка background задач, если первый токен bg . Завершение процесса по индексу, если первый токен term .

Во всех других случаях запускается процесс.

Реализация вспомогательных функций

Значение CONTINUE означает дальнейшее исполнение главного цикла командной оболочки. Значение EXIT прерывает выполнение главного цикла программы.

Функция quit отключает все callback функции по событию SIGCHLD - т. е. функции, выполняющиеся когда дочерний элемент был завершен. После этого завершает все активные процессы.

Основные цвета командной оболочки.

Часть 4. Главный цикл командной оболочки

Здесь и происходит вся магия. Взгляните на следующие строки. С помощью функции signal задаются callback функции на заданные события.

Событие SIGINT - срабатывает при нажатии комбинации ctrl-C , которое в дефолтном поведении завершает работу программы. В нашем же случае мы переназначаем его на завершение foreground процесса.

Событие SIGCHLD - срабатывает при завершении дочернего процесса созданyого с помощью системного вызова fork . В нашем случае мы переопределяем его на пометку фоновой задачи как выполненной с помощью функции mark_ended_task .

Все что описано в главном цикле командной оболочки можно описать словами:

Вывод информации о пользователе и текущей директории с помощью функции display

Чтение строки из стандартного потока ввода

Разбиение строки на токены

Выполнение ранее описанной функции execute , которая в зависимости от массива токенов выполняет нужное нам действие.

Нам осталось реализовать одну оставшуюся функцию display . Которая получает информацию о текущей директории с помощью функции getcwd и имя пользователя с помощью функции getpwuid .

Часть 5. Итоговый результат

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

Доброго времени! Интересует вопрос создания графической среды для linux. Интересно есть ли какие-нибудь мануалы или книги? Не спрашивайте зачем. Это просто для себя. Я бы хотел, чтобы те кто знает отписались по теме. Заранее спасибо!


Что есть графическая среда? Ты имеешь ввиду ДЕ? Или ВМ? Или ты вообще собрался новые иксы писать?

убиват. одних(не считая недо-поделок) достаточно


Книг нет. Начните с изучения lxde и razor-qt.


1. Учимся выводить точки на фреймбуфер.
2. Учимся выводить текст на фреймбуфер.
3. Пишем абстракцию системы рисования от фреймбуфера.
4. Учимся обрабатывать мышку.
5. Пишем вывод курсора с обработкой мышки.
6. Пишем простые классы для окон.
7. Пишем перетаскивание окон мышкой.
8. Пишем простой графический интерфейс.
9. Выкидываем все и переписываем заново, но лучше и более гибко.

вопрос создания графической среды для linux.

Я слышал, что они уже есть.


Мне почему-то кажется, что он имел в виду IDE.

Имеется ввиду не ИДЕ, а что-то типа Кеда или Гнома. note173, спасибо,єто и вправду ценная информация. Можно будет нагуглить по 'этому поводу. AITap, и вам спасибо огромное, тоже буду гуглить.

Всем спасибо за ответы!

Я в основном программирую в вебе

Тогда есть смысл сконцентрироваться на веб-приложениях.


dwm у него вообще только 1 файл, и он не превышает 2000 строк.

Если нужны кресты, то смотри на fluxbox.


В dwm хоть строк мало, но для изучения он не очень хорош. Там не очень мнемонический код, хотя если есть желание
PS: Запилите мне в dwm titlebar в плавающем режиме


SEVI

Интересует вопрос создания графической среды для linux.

вместе с иксами идут Over9000 мелких, и никому ненужных приложений (типа xclock), уверен, их сделали специально для вас.


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

Предлагаю другое: есть бэкэнд broadway для gtk3, который отправляет картинку окна в клиент на html5(canvas) по протоколу VNC. Ничего серьезного пока с этим не сделали, хотя уже работает. Можно попробовать реализовать веб-менеджер с возможностью запуска программы на удаленной машине и удаленного управления приложениями. Получится что-то вроде jolicloud, только с полноценным настольным софтом.



1. Учимся выводить точки на фреймбуфер.
2. Учимся выводить текст на фреймбуфер.
3. Пишем абстракцию системы рисования от фреймбуфера.
4. Учимся обрабатывать мышку.
5. Пишем вывод курсора с обработкой мышки.
6. Пишем простые классы для окон.
7. Пишем перетаскивание окон мышкой.
8. Пишем простой графический интерфейс.
9. Выкидываем все и переписываем заново, но лучше и более гибко.

По сабжу: рекомендуют читать исходники ЛХДЕ и xfce4.

Всем спасибо за ответы! Буду читать!


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


Книг нет. Начните с изучения lxde и razor-qt.

Поддерживаю, код в razor-qt не раздут и хорошо читается.


Лучше не майся ерундой, а присоединись к разрабам XFCE. Всяко нужнее, чем плодить велосипеды.

Читайте также: