Программный интерфейс оконной системы X, являющейся обычной сетевой службой, представлен библиотеками и соответствующими (библиотечными) вызовами к ним. Естественным образом, при наблюдении за работой разнообразных компонент утилита strace трассировки системных вызовов (к ядру) оказывается далеко не лучшим инструментом, а ее место занимает утилита трассировки библиотечных вызовов ltrace.
Содержимое
Трассировка X-библиотек и X-протокола
В листинге 7.30 показан пример трассировки библиотечных вызовов библиотек Xt, Xlib и Xrender при работе простейшего демо-клиента xeyes.
Трассировка библиотек X Window System
homer@ubuntu:~$ Idd $(whlch xeyes) | grep libX
llbXext.so.6 => /usr/ltb/i386-Unux-gnu/llbXext.so.6 (0xb772e000)
UbXmu.so.6 => /usr/ltb/l386-linux-gnu/llbXmu.so.6 (0xb7715000) llbXt.so.6 => /usrAlb/t386-llnux-gnu/llbXt.So.6 (0xb76b8000) llbXll.so.6 => /usr/ltb/i386-ltnux-gnu/llbXll.so.6 (0xb7584000)
UbXrender.so.l => /usr/ltb/t386-llnux-gnu/llbXrender.sa.l (0xb757a000) libXau.so.6 => /usr/llb/1386-ltnux-gnu/libXau.so.6 (0xb7350000)
ItbXdmcp.so.6 => /usr/ltb/1386-llnux-gnu/libXdmcp.so.6 (0xb7349000) honer@ubuntu:~$ Itrace -n 2 -l /usr/ltb/1386-linux-gnu/libXt.so.6 ‘ф
-l /usr/lib/l386-Unux-gnu/libXll.so.6 #
-l /usr/lib/i386-linux-gnu/llbXrender.so.l xeyes-l /usr/lib/i386-linux-gnu/llbXrender.so.l xeyes
XtAppAddTineOut(0x93ec868, 50, 0x804a780, 0x9405ba0, 0xbfd378e0) = 0x9405ea0
XtWlndowOfObject(0x9405ba0, 50, 0x804a780, 0xb756ccab, 0x93eefdc) = 0x600000c XQueryPolnter(0x93ed2f8, 0x600000c, 0xbfd37924, 0xbfd37928, 0xbfd3792c) = 1 XtWldgetToAppllcationContext(0x9405ba0, 0x40131942, …, …, 0xbfd378e0) = 0x93ec868
XtAppAddTineOut(0x8d84868, 50, 0x804a780, 0x8d9dba0, 0xbfa7c630) = 0x8d9e0e8
XtVHndowOfObject(0x8d9dba0, 50, 0x804a780, 0xb7553cab, 0x8d86fdc) = 0x600000c XQueryPointer(0x8d852f8, 0x600000c, 0xbfa7c674, 0xbfa7c678, 0xbfa7c67c) = 1 XFillRectangle(0x8d852f8, 0x600000c, 0x8d9del0, 44, 49) = 1
XRenderFindStandardFornat(0x8d852f8, 2, 0x65cblfc7, 0xbfc28ee3, 0) = 0x8d9d660
XRenderConpositeOoublePoly(0x8d852f8, 3, 0x600000a, 0x600000f, 0x8d9d660) = 0 XFlURectangle(0x8d852f8, 0x600000c, 0x8d9del0, 122, 50) = 1
XRenderFindStandardFormat(0x8d852f 8, 2, 0x47cc50bf, 0xbfc542b9, 0) = 0x8d9d660
XRenderCoppos\teOoublePoly(0x8d852f8, 3* 0x600000a, 0x600000f, 0x8d9d660) = 0 XtWidgetToAppltcattonContext(0x8d9dba0, 0x4024e60f, …, …, 0xbfa7c630) = 0x8d84868
Зная назначение библиотечных вызовов XQueryPointer, XFil(Recangle и XRenderCompositeDoublePoly, можно составить модель функционирования X-клиента, в котором легко увидеть цикл О опроса положения курсора при помощи XQueryPointer и цикл в перерисовки глаз стиранием их старого изображения при помощи XFillRectangle и отрисовки нового положения посредством XRenderCompositeDoublePoly(3).
Еще одним инструментом, разрешающим трассировать сообщения самого X-протокола, является xtrace, позволяющая увидеть обмен между X-клиентом и X-сервером.
Трассировка X-протокола
homer@ubuntu:~$ xtrace xeyes | grep -E 1 QueryPotnter | FillRectangle|RENDER’
000:<:0144: 8: Request(38): QueryPotnter wlndow=0x0600000c
000:>:0144:32: Reply to QueryPotnter: sane-screen=true(0x01) root=0x000000ae chtld=None(0x00000000) root-x=957 root-y=40 wtn-x=23 win-y=-ll mask=0
000:<:00c5: 20: Request(70): PolyFtllRectangle drawable=0x0600000c gc=0x06000007 rectangles={x=16 y=55 w=13 h=18};
000:<:00c6:304: RENDER-Request(149,10): Trapezotds op=Over(0x03) src=0x0600000a xSrc=0 ySrc=0 dst=©x0600000f naskFomat=0x00000024 trapezotds={top=54.831375 botton=55.656631
left={xl=20.236710 у1=70.672775 x2=22.805756 y2=71.498032}; rtght={xl=25.374802 yl=70.672775 x2=22.805756 y2=71.498032};};
Кроме xtrace, для анализа сообщений X-протокола при передаче по сети можно использовать анализатор сетевых пакетов wrieshark, ровно таким же образом, как и для анализа сетевых сообщений; любых других сетевых служб.
Большинство современных X-клиентов не прибегают напрямую к помощи низкоуровневых библиотек, таких как Xlib и Xrender, а используют высокоуровневые библиотеки виджетов, отрисовывающие их при помощи сообщений X-протокола. В примере ниже показана простейшая программа на языке программирования С, использующая библиотеку виджетов Gtk, а далее приведены ее компиляция и трассировка ее библиотечных вызовов к libgtk-x11-2.e.so.0.
Язык С и библиотека виджетов Gtk
Kxner@ubuntu:~$ cat hello.c ^Include <gtk/gtk.h>
static void temlnate(GtkWldget *wldget, gpolnter data) { gtk_matn_qutt();
}
Int roaln(lnt argc, char *argv[]) {
GtkWldget *wlndow, *button, *label, *vbox;
gtk_lnlt (&argc, &argv);
window = gtk_wtndow_new(GTK_WINDOW_TOPLEVEL); vbox = gtk_vbox_new(TRUE, 0); gtk_contalner_add(GTK_CONTAINER (window), vbox);
label = gtk_label_new(«Hello, world!»); gtk_contalner_add(GTX_CONTAINER (vbox), label);
button = gtk_button_newjwlth_label(«Qult»); gtk_contalner_add(GTK_CONTAINER (vbox), button);
g_slgnal_connect(button, «clicked», G_CALLBACK (terminate), NULL); . gtk_wldget_show_all (window); gtk_maln ();
return 0;
}
Интерфейс программы выстраивается из виджетов окна (window) и вертикального контейнера (vbox), который добавляется в это окно. В контейнер последовательно добавляются и виджеты текстовой метки (label) и кнопки (button), сигнал нажатия (clicked) на которую связывается с обработчиком — функцией ternlnate.
По запросу отображения окна библиотека прорисовывает виджеты помощи X-протокола, после чего запускается главный цикл обработки поступающих событий X-протокола (щелчки кнопкой мыши, нажатия клавиш и т. д.), который прекращается при срабатывании обработчика сигнала нажатия (clicked) на виджет кнопки.
Трассировка библиотеки Gtk
honer^jbuntu:~$ gcc hello.c -o hello $(pkg-config —cflags —libs gtk+-2.0) honer@jbuntu:~$ Iddtree hello | grep libgtkhoner^jbuntu:~$ gcc hello.c -o hello $(pkg-config —cflags —libs gtk+-2.0) honer@jbuntu:~$ Iddtree hello | grep libgtk
llbgtk-xll-2.0.so.0 => /usr/llb/l386-linux-gnu/llbgtk-xll-2.0.so.0 honer@ubuntu:~$ Itrace -n2 -l /usr/llb/i386-linux-gnu/libgtk-xll-2.0.so.0 ./hello gtk_lnlt(0xbfc98440, 0xbfc98444, 0x8049ff4, 0Х80488Ы, -1) = 1
gtk_vandow_new(0, 0xbfc98444, 0x8049ff4, 0Х80488Ы, -1) = 0x8302000
gtk_vbox_new(l, 0, 0x8049ff4, 0Х80488Ы, -1) = 0x82ab858
gtk_contalnerjget_type(1, 0, 0x8049ff4, 0Х80488Ы, -1) = 0x82e29b0
gtk_c£xitalner_add(0x8302000, 0x82ab858, 0x8049ff4, 0x80488bl, -1) = 0
gtk_label_new(0x8048960, 0x82ab858, 0x8049ff4, 0Х80488Ы, -1) = 0xb5b06608
gtk_container_get_type(0x8048960, 0x82ab858 , 0x8049ff4, 0Х80488Ы, -1) = 0x82e29b0 gtk_container_add(0x82ab858, 0xb5b06608, 0x8049ff4, 0Х80488Ы, -1) = 0 gtk_button_new_with_label(0x804896e, 0xb5b06608, 0x8049ff4, 0Х80488Ы, -1) — 0x830a010 gtk_container_get_type(0x804896e, 0xb5b06608, 0x8049ff4, 0Х80488Ы, -1) = 0x82e29b0 gtk_container_add(0x82ab858, 0x830a010, 0x8O49ff4, 0Х80488Ы, -1) = 0 gtk_wldget_show_all(0x8302000, 0x8048973, 0x8048764, 0, 0) =2
gtkjnain(0x8302000, 0x8048973, 0x8048764, 0, 0 «unfinished . ..> gtkjnaln_qult(0x82ab858, 0xb73d0f30, 0xb72e5160, 0xb72e5243, 0x830a010) = 0 <• •• gtkjnaln resumed» ) =0
+++ exited (status 0) +++
Аналогичным образом выглядят и работают программы, использующие Gtk и на других языках программирования, например на Python, что проиллюстрировано в листинге ниже.
Интерпретатор Python и библиотека интерфейсных элементов Ctk
honer@ubuntu:~$ cat gtk-hello.ру #! /usr/bin/python
import gtk
w = gtk. WindowQ box * gtk.VBox() w.add(box)
l = gtk.LabelC»Hello, world!”) box.add(l)
b = gtk.Button(«Quit») box.add(b)
def terminate(o): gtk.main_quit()
b.connect(«clicked», terminate)
w.show_all()
gtk.mainQ
Каждая библиотека виджетов при ее использовании для построения пользовательского интерфейса обладает своей спецификой, но в целом имеет много общего с другими библиотеками интерфейсных элементов. Для сравнения, в листинге ниже приведена программа на языке Python, использующая библиотеку Qt, в которой можно найти много общего с программой, написанной на том же языке, но использующей библиотеку Gtk.
Интерпретатор Python и библиотека интерфейсных элементов QtGui
homer@ubuntu:~$ cat qt-hello.py #!/usr/bin/python
import sys
from PyQt4 import QtGui, Qt a = QtGui. QApplication( sys. argv)
w = QtGui.QWidget() box = QtGui.QVBoxLayout() w.setLayout(box)
\ Я QtCui.QLabel(«Hello, worldl») w.layout().addWidget(l)
b ■ QtGui.QPushButton(«Quit») w. layout (). addWtdget (b)
def terminate(): a.qultQ
w.show()
a.connect(b, Qt.SICWAL(’’clicked()»), terminate) a.exec_()
Библиотека виджетов W:[Tk] среди прочих других библиотек занимает, пожалуй, особенное место за счет языка W:[Tcl], в качестве расширения которого специально и разрабатывалась. В отличие от языков С и Python, приведенных выше, и многих других «настоящих» систем программирования, Tel (Tool Command Language) является инструментальным языком, родственным семейству языков командного интерпретатора bash, ksh, csh, zsh и пр.
Tcl-интерпретатор имеет «обычную» оболочку tclsh(l), Tel shell, и «оконную» оболочку wish(1), windowing shell, со встроенными командами к библиотеке виджетов Tk. Среди прочих вариантов Х-клиента с использованием различных языков программирования и библиотек виджетов имеет самый простой и очевидный синтаксис, похожий на синтаксис языка командного интерпретатора.
Графический интерфейс, с которого начинается /первое «визуальное» знакомство любого начинающего пользователя с современной операционной системой Linux, на поверку оказывается самой «сложной» ее подсистемой.
Оконная система X Window System использует в своей работе практически все рассмотренные сущности операционной системы — программы и библиотеки, процессы и нити, драйверы устройств и их специальные файлы, локальные (файловые) сокеты, сетевую подсистему и сетевые сокеты, разделяемую память, отображение файлов в память и даже службу SSH. Даже выход первой версии ядра Linux был практически «приурочен» к моменту успешного за пуска и стабильной работы оконной системы X.
Не менее изощренными (а может быть, и более) в использовании услуг, предоставляемых приложениям разнообразными компонентами операционной системы, являются графические среды пользователей, такие как GNOME или KDE.
Таким образом, понимание происходящих в недрах Linux процессов, стоящих за графическим интерфейсом, пожалуй, сможет служить хорошей мерой проникновения в предмет внутреннего устройства этой замечательной операционной системы.