Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Программирование под *nix > Общие вопросы программирования
Перезагрузить страницу Принципы оконного интерфейса
Ответ
 
Опции темы Опции просмотра
  (#46 (permalink)) Старый
Dian Dian вне форума
Member
 
Сообщений: 5,243
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 17.09.2004
По умолчанию 30.11.2007, 18:10

В смартфонах архитектура ARM, на обычном компе - x86, стало быть без перекомпиляции никуда. Современные компиляторы в большинстве своём умеют генерить код под разные платформы. Точнее, без перекомпиляции - только байт-код (java, .net).
Цитата:
Запустится ли в общем случае такая прога на WinCE?
Спорный вопрос - системы все-таки разные. Микрософт вроде заявляли совместимость, но на деле не факт, что она даже скомпилится для CE.
Цитата:
Есть ли Linux для смартфонов?
Специально для смартов - не знаю, а вот то, что оригинальное ядро портировано на ARM - это 100%. Следовательно, все системные вызовы ядра те же и проблем, как в случае с Win/CE быть не должно.


Наконец-то добрался до изучения pthreads и набросал пару вещей
http://dian4all.narod.ru/misc/pthreads.cpp - просто два потока
http://dian4all.narod.ru/misc/pthreads_a.cpp - с общими данными
Ответить с цитированием
  (#47 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 03.12.2007, 13:42

Цитата:
И тут я хотел со своей не совсем профессиональной стороны предложить такое решение. Достаточно организовать группу переменных (область памяти), которая будет доступна как первой, так и второй подпрограмме.
Такое решение организовано в POSIX используют набор функций shmget,shmdt,shmat,shmctl.
Так же возможно работа потоков через каналы, именованные каналы, сокеты, файлы, файлы в памяти, через файловую систему proc.
Ответить с цитированием
  (#48 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 03.12.2007, 13:46

Цитата:
P.S. Кстати, еще один малость оффтопный вопрос - услышал, что Windows и Linux написаны на чистом Си, а не на С++ - это правда?
Код ядра Linux написан на чистом C.
Что самое интересное портирован под достаточно большое количество процесоров.
Ответить с цитированием
Ads
  (#49 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 03.12.2007, 16:12

[quote]Попросил бы кого-нибудь из уважаемых участников форума переписать мою программку, код которой я приводил выше, нормальным способом, по-настоящему. Интересно, как она будет реально выглядеть, написанная под UNIX - Linux.
Предлагается внести следующее изменение в работу основной функции
Код:
// создаеш семафор 
pthread_mutex_t mutex;
  int main()
{
  // устанавливаем обработчик сигналов
  struct sigaction act;
  act.sa_handler = fun_handler;
  sigaction(USER1,&act,NULL);
  // выделяеш обший кусок памяти
  int m_id;
  char * buff;
  m_id = shmget(0x77, 4096,IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
  buff = (char*)shmat(m_id,0,0);
  //захватываеш семафор   
  pthread_mutex_lock(&mutex);
  //создание потока 
  pthread_t th;
  pthred_create(&th, NULL, &pth_fun,NULL);
  // открытие файла по считыванию данных с клавиатуры
  int fd = open("/dev/tty1",O_RDONLY); 
  for(;;){
    // считываем нажатые клавиши
    с = read(fd,buff,1);
    if(c){ // если есть даные 
      // освобождаем семафор
      pthread_mutex_unlock(&mutex);
      // даем возможность потоку обработать буфер
      pause();
      //захватываеш семафор   
      pthread_mutex_lock(mutex);
    }
  }
 return 0;
}
void * pth_fun(void * unused)
{
  int m_id;
  char * buff;
  // определяеш id обшего куска памяти
  m_id = shmget(0x77, 0,0);
  buff = (char*)shmat(m_id,0,0);
  //захватываеш семафор   
  pthread_mutex_lock(mutex);
  // выводим на экран символ
  printf("%c",buff[0]);
  //посылает сигнал сам себе
  kill(USER1);
  // освобождаем семафор
  pthread_mutex_unlock(&mutex);
}
Набросал немного от руки. Приблезительно такой принцип работы. Вполне могут быть не учтенные нюансы.
Ответить с цитированием
  (#50 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 03.12.2007, 22:30

Цитата:
Код ядра Linux написан на чистом C.
+ассемблер. В C нет доступа к регистрам, портам ввода-вывода (на x86) и т.д.
Ответить с цитированием
Ads.
  (#51 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 03.12.2007, 22:37

Цитата:
Ну где то так .
1. Зачем использовать IPC в одном процессе?! Память у потоков и так общая.
2. kill имеет два аргумента. Вы, наверное, имели в виду raise. Лучше было использовать pthread_kill (а еще лучше - condition variable).
3. В pth_fun я бы SIGUSR1 заблокировал.

Еще подумал: вместо pause надо было для надежности использовать sigsuspend.
Ответить с цитированием
  (#52 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 03.12.2007, 23:37

Моя версия с потоками:
Код:
#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

struct {
  char data[10];
  int size;
  pthread_cond_t cond;
} buf;

void* computation (void*);

int
main ()
{
  pthread_cond_init (&buf.cond, NULL);

  pthread_t thread;
  pthread_create (&thread, NULL, computation, NULL);

  int fd = STDIN_FILENO;
  int res;
  struct termios ios_old, ios;
  res = tcgetattr (fd, &ios_old);
  ios = ios_old;
  ios.c_lflag &= ~ICANON;
  ios.c_cc[VMIN] = 1;
  ios.c_cc[VTIME] = 0;
  res = tcsetattr (fd, TCSAFLUSH, &ios);

  char c;

  while (read (fd, &c, sizeof (c)) > 0) {
    pthread_mutex_lock (&mutex);
    if (buf.size < sizeof (buf.data)) {
      buf.data[buf.size] = c;
      buf.size++;
    }
    pthread_cond_signal (&buf.cond);
    pthread_mutex_unlock (&mutex);
  }

  tcsetattr (fd, TCSAFLUSH, &ios_old);
  return 0;
}

void*
computation (void *arg)
{
  for (;;) {
    char c;
    pthread_mutex_lock (&mutex);
    while (buf.size == 0) {
      pthread_cond_wait (&buf.cond, &mutex);
    }
    c = buf.data[0];
    buf.size--;
    memcpy (&buf.data[0], &buf.data[1], buf.size * sizeof (buf.data[0]));
    pthread_mutex_unlock (&mutex);

    putchar (c);
    fflush (stdout);
  }
}
Ответить с цитированием
  (#53 (permalink)) Старый
Matematic Matematic вне форума
Member
 
Аватар для Matematic
 
Сообщений: 388
Сказал(а) спасибо: 31
Поблагодарили 8 раз(а) в 8 сообщениях
Регистрация: 15.01.2007
По умолчанию 04.12.2007, 05:42

Спасибо Dian'у, Yaroslav'у и Alexey'ю Dejnek'е за то, что откликнулись и прислали свои коды. Было по-человечески очень приятно! Все исходники скопировал, почитаю, поразбираюсь в них.

Пара уточняющих вопросов.

1. Почему функция потока, вызываемого из main(), имеет в качестве типа возвращаемого значения void* ? С чем связана такая договоренность в UNIX, какой ее смысл?

2. Как я понял, создаем новый поток мы, используя некоторую самую обычную функцию нашей программы. Созданием потока из этой функции занимается некоторая другая функция то ли библиотеки unistd языка C, то ли самой системы UNIX. Скорее всего, думаю, функция библиотеки C вызывает соответствующую функцию ОС и этим лишь скрывает ее непосредственное использование от программиста (поясните, так ли это). Не совсем понятно, при создании нового потока из функции копируется ли содержимое этой функции в новую специально выделенную для этого область памяти или же просто операционной системе передается адрес (указатель) этой функции, который заносится ею в специальную таблицу, где и создается какой-то элемент списка, соответствующий новому потоку? И при этом функция, ставшая вдруг "потоком" остается физически на том же месте, без всякой дубликации?

Не исключено, что для того, чтобы сделать из простой функции "поток", необходимо знать не только ее начальный, но и конечный адрес. В случае варианта 1 (с дубликацией кода) это просто необходимо (иначе неизвестно будет, на каком месте закончить копирование). Но создание потока осуществляется специальной функцией pthread_create, а функции, как известно, в состав компилятора не входят и знать об адресе конца другой функции ничего не могут (т. е. никакой системной информации о программе на этапе компиляции в них заложено быть не может, а на этапе выполнения врятли они уже что-то узнают). Или же реально осуществлен вариант 2 (передача адреса без изменения места нахождения функции) и при этом ОС знает только точку входа в новый поток (адрес функции), а место окончания соответствующей подпрограммы ей неизвестно, т.к. адресное пространство обоих потоков, и дочернего, и материнского, общее, не защищено одно от другого дескрипторами, как в случае различных процессов, и подобная информация совершенно не нужна операционной системе? И проблема определения правой адресной границы функции отпадает сама собой?

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

Ну и последнее. В соседней ветке я задавал вопрос о книжках по Unix'у и Linux'у. Хотелось бы, чтобы кто-то из знающих людей что-то мне посоветовал, порекомендовал. В книжных магазинах в соответствующих отделах эта тема представлена довольно бедно (в отличие от языков программирования, в особенноости C/C++), поэтому самому найти что-то приличное не так просто. Вот тема.
Ответить с цитированием
  (#54 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 04.12.2007, 07:53

Цитата:
1. Почему функция потока, вызываемого из main(), имеет в качестве типа возвращаемого значения void* ? С чем связана такая договоренность в UNIX, какой ее смысл?
Поток, как и процесс, может завершиться с определённым результатом. Процесс возвращает код возврата - int, поток - указатель.

Цитата:
2. Как я понял, создаем новый поток мы, используя некоторую самую обычную функцию нашей программы. Созданием потока из этой функции занимается некоторая другая функция то ли библиотеки unistd языка C, то ли самой системы UNIX. Скорее всего, думаю, функция библиотеки C вызывает соответствующую функцию ОС и этим лишь скрывает ее непосредственное использование от программиста (поясните, так ли это).
Есть стандарт(ы), описывающий UNIX с точки зрения языка C, и семейство операционных систем (ядро + библиотека языка C + набор утилит), следующих этим стандартам. Разделение обязанностей между ядром и libc зависит от конкретной системы. Например, функция open (открытие файла) должна возвращать код ошибки в переменной errno. В GNU/Linux есть системный вызов, принимающий аргументы в регистрах, и возвращающий либо номер файла, либо код ошибки, а также функция libc, перекладывающая аргументы в регистры, делающая соответствующий системный вызов и перекладывающая код ошибки (если есть) в errno. В GNU/HURD ядра (Mach, L4) вообще не представляют себе, что такое "файлы"; функция open библиотеки libc делает рекурсивные запросы к серверам (другим пользовательским процессам), реализующим куски файловой системы. Внешне - все как в Unix, внутри - все иначе.

Цитата:
Не совсем понятно, при создании нового потока из функции копируется ли содержимое этой функции в новую специально выделенную для этого область памяти или же просто операционной системе передается адрес (указатель) этой функции, который заносится ею в специальную таблицу, где и создается какой-то элемент списка, соответствующий новому потоку? И при этом функция, ставшая вдруг "потоком" остается физически на том же месте, без всякой дубликации?
1. Все потоки (в отличие от процессов) работают в одном адресном пространстве, при создании нового потока ничего копировать не надо.
2. Поток - это не "функция" и он не создается "из функции". При запуске потока нужно указать, какой код нужно начать выполнять; после запуска он может делать все, что ему заблагорассудится. Для языка C в аргументе pthread_create указывается функция, которой нужно передать управление при старте потока, но она вполне может вызывать любые другие функции.
Ответить с цитированием
  (#55 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 04.12.2007, 08:39

Цитата:
1. Зачем использовать IPC в одном процессе?! Память у потоков и так общая.
2. kill имеет два аргумента. Вы, наверное, имели в виду raise. Лучше было использовать pthread_kill (а еще лучше - condition variable).
3. В pth_fun я бы SIGUSR1 заблокировал.

Еще подумал: вместо pause надо было для надежности использовать sigsuspend.
1. Так ка программа всеже учебная просто хотелось продемонстрировать как можно больше возможностей.
2. Да не допечатал определение своего PID.
3. В pth_fun ты не можеш заблокировать сигнал. Сигнал посылается только потоку.
Ответить с цитированием
  (#56 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 04.12.2007, 08:45

Цитата:
+ассемблер. В C нет доступа к регистрам, портам ввода-вывода (на x86) и т.д.
В основном ассемблер используется в основном в блоке инициализации, и то очень немного 99% написано на С.
Ответить с цитированием
  (#57 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 04.12.2007, 20:59

Цитата:
3. В pth_fun ты не можеш заблокировать сигнал.
Я имел в виду дочерний поток (исполняющий pth_fun).

Цитата:
Сигнал посылается только потоку.
Вообще-то, kill посылает сигнал процессу, т.е. совокупности всех потоков. Поймать его вполне может и дочерний поток, тогда pause в родителе не сработает. Если пример должен был продемонстрировать работу с процессами, ребенок должен был посылать сигнал по pid родителя (который еще нужно получить), родитель должен был постоянно держать сигнал заблокированным, а принимать его в sigsuspend.
Ответить с цитированием
  (#58 (permalink)) Старый
Yaroslav Yaroslav вне форума
Member
 
Сообщений: 166
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.10.2004
По умолчанию 05.12.2007, 09:25

Цитата:
Вообще-то, kill посылает сигнал процессу, т.е. совокупности всех потоков. Поймать его вполне может и дочерний поток, тогда pause в родителе не сработает. Если пример должен был продемонстрировать работу с процессами, ребенок должен был посылать сигнал по pid родителя (который еще нужно получить), родитель должен был постоянно держать сигнал заблокированным, а принимать его в sigsuspend.
Сигнал ты посылаеш по PID, соответственно сигнал ты можеш послать любому потоку, только вот определить какой PID у какого потока сложновато (когда их несколько),
да и функция обработки одна на процесс.
Ответить с цитированием
  (#59 (permalink)) Старый
Arachnelis Arachnelis вне форума
Member
 
Сообщений: 1,324
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.07.2007
Thumbs up 05.12.2007, 13:15

У любой UI-библиотеки может выделить два важнейших параметра - быстрота проектирования UI с ее использованием и быстродействие. Обычно эти параметры являются взаимоисключающими. Но теоретически библиотеку можно наполнить широким спектром возможностей - используешь одни классы - быстро пишешь, используешь другие - получаешь доступ к ОС почти напрямую, и, как следствие, скорость.

Вопросы насчет QT и wxWidjets:

1. Какая из них в бОльшей степени соответствует одновременно обоим этим критериям?
Т.е. в какой из них присутствует как раз широкий набор классов на выбор?

2. Какой идеологии в принципе следует та и другая?
Ответить с цитированием
  (#60 (permalink)) Старый
Alexey Dejneka Alexey Dejneka вне форума
Member
 
Сообщений: 451
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.11.2004
По умолчанию 05.12.2007, 23:14

Цитата:
Сигнал ты посылаеш по PID, соответственно сигнал ты можеш послать любому потоку, только вот определить какой PID у какого потока сложновато
PID - это process identifier, а не thread identifier. В POSIX все потоки (threads), принадлежащие одному процессу (process), имеют один и тот же PID. Функция kill (в отличие от pthread_kill) посылает сигнал именно процессу, а обработать его может любой из потоков.

В старых версиях Linux это было не так, но в NPTL все исправили.

Цитата:
функция обработки одна на процесс
Совершенно верно! И, тем самым, одна на все потоки.
Ответить с цитированием
Ads
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Некоторые принципы по написанию программ, для новичков dect Общие вопросы создания ПО 15 24.09.2011 19:18
Общие принципы организации синтаксического разбора в С++ 45182 Вопросы начинающих программистов 2 09.01.2011 18:41
Программа демонстрирующая принципы ООП (полиморфизм, инкапсуляцию, наследование) TidalAeon Вопросы начинающих программистов 0 11.12.2010 16:32
Принципы управления DVD и CD приводами tumanovalex Железо. Написание драйверов 0 29.08.2008 00:21
Принципы решения написания программы Frullani Lisp 2 27.09.2007 19:23
Принципы форматирования файлов shatush Общетематический 3 29.06.2007 23:16
Создание оконного приложения для Windows с 98 на VS2005 Antsu Visual C++ 5 17.01.2007 10:34
Объясните общие принципы работы CAsyncSocket Palmman Сетевое программирование 2 02.10.2006 20:28
Принципы создания средствами VC++ 6.0 интерфейса типа "проводник" Postum Visual C++ 8 26.01.2005 18:10
Принципы написания трояна Anonymous Delphi 30 19.03.2004 16:37
Принципы DoS-атак как их создавать Felix Delphi 2 11.01.2004 06:27
Принципы работы менеджера виртуальных экранов lv Visual C++ 0 01.11.2003 05:24



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов