Страницы

Поиск по вопросам

Показаны сообщения с ярлыком posix. Показать все сообщения
Показаны сообщения с ярлыком posix. Показать все сообщения

воскресенье, 29 марта 2020 г.

Синхронизация вывода потоков POSIX

#cpp #c #многопоточность #pthread #posix


Нужно что бы два потока параллельно печатали на экран. (Первый поток печатает числа
1,2,3...10 Второй - 100,200,300...1000). Причём вывод должен быть синхронизирован:
сначала родительский поток выводит первую строку, затем дочерний первую, затем родительский
вторую строку, затем дочерний вторую и т.д.(100,1,200,2,300,3...) Использовать нужно
мьютексы.

pthread_mutex_t mut;

void printt(int i){
   pthread_mutex_lock(&mut);
   cout<


Ответы

Ответ 1



Предупреждение: согласно POSIX данное решение даёт UB [1], хотя и, судя по всему, он работает в реализации pthreads от glibc/linux; он приведен лишь для справки/как идея и не должен использоваться. Спасибо @VTT за замечание. Для решения задачи нужно количество мьютексов равное количеству потоков. Идея в том, чтобы мьютексы захватывались разными потоками попеременно, т.е. входя в критические секции нужно захватывать свой мьютекс, а при выходе отпускать мьютекс следующего потока. Само собой, перед началом выполнения свободным должен быть отпущен только один мьютекс. В итоге получается нечто следующее: pthread_mutex_t mut1; pthread_mutex_t mut2; void printt1(int i){ pthread_mutex_lock(&mut1); cout<

Ответ 2



Функция printt печатает локальную переменную i, к которой у других потоков нет доступа, а синхронизация не ожидает завершения записи предыдущей строки другим потоком. Также полностью отсутствует обработка ошибок.

Ответ 3



Без сигналов , чтоб другой поток проснулся неудобно, придумал только сон. Вроде бы пашет. Нужна переменная для знака кому какая очередь. // g++ -pthread mutex-semaph.cpp #include # include # include pthread_mutex_t mut; int queue = 1 ; // или 2 void printt(int i, int q){ Again : pthread_mutex_lock(&mut); if(queue == q) std::cout<

Ответ 4



Сделайте разделяемую volatile переменную и mutex. Присвойте переменной 1, что означает печать будет проводить первый поток. Запустите потоки. В каждом потоке в цикле захватываете mutex и читаете значение переменной. Если значение переменной в первом потоке равно 1, то он печатает данные и присваивает переменной 2. Аналогично, второй поток производит печать если значение переменной равно 2, после чего устанавливает ее в 1. (Обратите внимание, чтение и модификация переменной защищены mutex-ом.) Затем поток в любом случае снимает блокировку и (для оптимизации эффективности) вызывает pthread_yield. Конкретно в вашем случае с внешним циклом и анализом очередности печати внутри printt() (очевидно, с целью не вытаскивать работу с mutex на уровень управления циклом) в этой функции нужно дождаться, пока общая переменная не примет нужного значения. Впрочем, хватит общих слов. Вот немного модифицированный ваш код из текста вопроса. avp@avp-ubu1:hashcode$ cat t-seq-pri.c #ifdef __cplusplus #include using namespace std; #else #define _GNU_SOURCE #include #endif #include pthread_mutex_t mut; volatile int turn; void printt(int i, int q){ int pri = 0; do { pthread_mutex_lock(&mut); if (turn == q) { #ifdef __cplusplus cout<

среда, 22 января 2020 г.

Как проверить, что поток NSThread заблокирован?

#objective_c #многопоточность #posix #pthread


Давно хотел узнать, возможно ли для тестирования (unit testing) сделать следующее:
Можно ли добавить в NSThread метод, который будет показывать, заблокирован (остановлен)
ли данный поток или нет?
Я предполагаю, что, если эта задача в принципе решается, было бы удобно сделать отдельную
категорию NSThread+IsBlocked, содержащую такой метод и вполне достойную своего отдельного
репозитория на Github ;)
Прямо сейчас я занимаюсь NSCondition - вот цепь вызовов, которую для остановки потока
делает -[NSCondition wait]:
[NSCondition wait] 
pthread_cond_wait$UNIX2003
_pthread_cond_wait
__psynch_cvwait

Кроме NSCondition есть множество других способов блокировать/останавливать потоки
NSThread: dispatch semaphores, NSConditionLock, [NSThread sleepForTimeInterval:] и
т.п. - я знаю Objective-C лишь на уровне iOS-разработчика, поэтому не имею представления,
возможно ли написать такой метод, который будет показывать факт блокировки потока сразу
для всех этих способов. Буду признателен даже за метод, работающий только с NSCondition
и __psynch_cvwait.
Вот простой пример того, чего я хотел бы добиться (искомый метод - isBlocked):
// Some test case
// ...

__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];

dispatch_async(someQueue(), ^{
    thread = NSThread.currentThread;

    [condition lock];
    [condition wait];
    [condition unlock];
});

while(1) {
    NSLog(@"Thread is blocked: %d", thread.isBlocked);
}

Я не знаток чистого C и POSIX threads, поэтому, если знаете ответ, сделайте его,
пожалуйста, развёрнутым.
Примечание: речь идёт именно о блокировании (остановке) потока, а не о проверке isLocked
вроде "Находимся ли мы @synchronized {}?"     


Ответы

Ответ 1



Мир - Россия 1:0 - ответ получен в топике, который параллельно с этим был открыт мной на SO: Is it possible to check if an NSThread is blocked?. Там см. принятый ответ. Очень изящное решение для NSCondition. Заодно показывающее, как можно красиво модифицировать поведение классов, подменяя методы друг другом (по логике отдалённо напоминает alias_method_chain в Ruby).

понедельник, 30 декабря 2019 г.

переменная errno в многопоточной программе

#c #posix


здравствуйте, допустим, в нескольких программных нитях(потоках) вызываем функцию
read... и она завершается в одном из нитей, допустим, с errno = EAGAIN, в другой с
errno = EBADF... потокобезопасна ли переменная errno, или в каждой нити она своя? 
    


Ответы

Ответ 1



Короткий ответ -- да, errno потокобезопасна. Это требование Posix. (смотри этот ответ)

Ответ 2



Смотрим man errno: errno is thread-local; setting it in one thread does not affect its value in any other thread.

воскресенье, 22 декабря 2019 г.

Где взять POSIX стандарт?

#c #стандарт #posix


Хочу написать маленькую libc для своего микро-дистрибутива linux по POSIX стандарту,
после гугления я понял, что его принимает IEEE, если нет, то поправите меня, ибо я
не особо в этих стандартизациях разобрался.  

На сайте IEEE платный.  

Как писать по этому стандарту бесплатно, и где взять актуальную версию стандарта?
    


Ответы

Ответ 1



некоторые важные версии публикуются для свободного доступа на сайте организации the open group. например: The Single UNIX® Specification, Version 2 © 1997 The Open Group The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition © 2001-2004 The IEEE and The Open Group The Open Group Base Specifications Issue 7 IEEE Std 1003.1™, 2013 Edition © 2001-2013 The IEEE and The Open Group

вторник, 26 ноября 2019 г.

Зачем в POSIX-системах вызов fork() создаёт полную копию?


Изучая операционные системы задал себе вопрос: зачем в POSIX-подобных системах пр
создании процесса избран путь полного копирования родительского процесса в дочерни
и только после этого с помощью сис.вызова execve новый процесс перезаписывается полезны
содержимым? В чем смысл передавать дочернему весь образ памяти, строки конфигурации и т.д., когда, к примеру, в Windows создаётся, ну очень грубо говоря, "пустое ничего" и уже ему задаются аргументы, в поле памяти записывается выполняющаяся программа и ещё 7-8 стандартных параметров?

Вопрос иерархий тоже не затрагиваю, тут с этим все однозначно и польза от подход
ясна. У меня нет цели захейтить один из путей или развести холивар, мне хочется разобраться
какие плюсы и минусы у обоих способов. Ведь не просто так 'fork'у не нашли замены в течении нескольких десятилетий, так ведь? Да, я знаю, что большинство современных POSIX систем при вызове fork() используют COW принцип, но раньше ведь было не так.

Спасибо тем, кто постарается простым (а можно и не простым) языком описать суть на столько разных подходов. Принимаются любые ссылки с описанием.
    


Ответы

Ответ 1



Благодаря наводке кемментатора был найден англоязычный ресурс с идентичным вопросом В комментариях найден ответ, который по моему мнению, более всего соответствует действительности. Итак: Существует две философии создания процесса: fork с наследованием содержимого родител и создание пустого процесса с заданием аргументов (create). Очевидно, Unix используе fork. (Например, OSE и VMS используют метод create.) Unix имеет много наследуемых характеристик процесса. Через наследование эти характеристики могут быть добавлены новому процессу без измененя существующих программ. Используя модель create-with-arguments, добавление новых характеристик будет означать добавление новых аргументов в вызов create. Модель Unix проще. Имея вышеописанное существует возможность иметь также очень полезную модель fork-without-exec где процесс может разбиться на несколько частей. Это было особо важно, когда не был никакой формы асинхронного ввода-вывода, и полезно, когда вы используете несколько процессоров в системе. По сути, это позволяет контейнеризировать несколько «программ» в одну программу, поэтому нет места для рассогласования или несоответствий версий и т.д. Модель fork / exec также дает возможность определенному дочернему процессу наследоват среду, настроенную между разветвлённым процессом и exec. Особенно, такие вещи, как унаследованные файловые дескрипторы. Модель создания (create model) не дает возможности наследовать все, что не было предусмотрено создателями вызова create. Некоторые системы также могут поддерживать динамическую компиляцию собственного кода где процесс фактически создает собственную программу с собственным кодом. Другими словами он хочет, чтобы новая программа записывала себя «на лету», без необходимости проходить цикл исходного кода / компилятора / компоновщика и занимать дисковое пространство. Модель fork поддерживает это, модель создания обычно нет.

Ответ 2



Я думаю, что суть fork в минимизации усилий программиста (обратите внимание, программиста а не железа) при создании нового процесса, окружение которого уже подготовлено всей историей жизни родителя (и остальных предков). Вам остается только добавить что-то свое (впрочем, ничто не мешает и отбросить это груз). Причем, делаете это безопасно для родителя, не оказывая воздействия на других его потомков. В простейшем случае вы можете даже не менять исполняемую программу, но в большинств случаев все же почти сразу делаете это (вызываете exec). Но и в этом случае fork очевидно полезен, позволяя изолировать какую-то подготовку к такой перемене уже в новом процессе. Да что тут много говорить, лучше почитайте The Evolution of the Unix Time-sharing System. В общем, fork это просто очень красивая концепция.

суббота, 9 марта 2019 г.

Как проверить, что поток NSThread заблокирован?

Давно хотел узнать, возможно ли для тестирования (unit testing) сделать следующее: Можно ли добавить в NSThread метод, который будет показывать, заблокирован (остановлен) ли данный поток или нет? Я предполагаю, что, если эта задача в принципе решается, было бы удобно сделать отдельную категорию NSThread+IsBlocked, содержащую такой метод и вполне достойную своего отдельного репозитория на Github ;) Прямо сейчас я занимаюсь NSCondition - вот цепь вызовов, которую для остановки потока делает -[NSCondition wait]: [NSCondition wait] pthread_cond_wait$UNIX2003 _pthread_cond_wait __psynch_cvwait Кроме NSCondition есть множество других способов блокировать/останавливать потоки NSThread: dispatch semaphores, NSConditionLock, [NSThread sleepForTimeInterval:] и т.п. - я знаю Objective-C лишь на уровне iOS-разработчика, поэтому не имею представления, возможно ли написать такой метод, который будет показывать факт блокировки потока сразу для всех этих способов. Буду признателен даже за метод, работающий только с NSCondition и __psynch_cvwait. Вот простой пример того, чего я хотел бы добиться (искомый метод - isBlocked): // Some test case // ...
__block NSThread *thread; NSCondition *condition = [NSCondition alloc] init];
dispatch_async(someQueue(), ^{ thread = NSThread.currentThread;
[condition lock]; [condition wait]; [condition unlock]; });
while(1) { NSLog(@"Thread is blocked: %d", thread.isBlocked); } Я не знаток чистого C и POSIX threads, поэтому, если знаете ответ, сделайте его, пожалуйста, развёрнутым. Примечание: речь идёт именно о блокировании (остановке) потока, а не о проверке isLocked вроде "Находимся ли мы @synchronized {}?"


Ответ

Мир - Россия 1:0 - ответ получен в топике, который параллельно с этим был открыт мной на SO: Is it possible to check if an NSThread is blocked?.
Там см. принятый ответ. Очень изящное решение для NSCondition.
Заодно показывающее, как можно красиво модифицировать поведение классов, подменяя методы друг другом (по логике отдалённо напоминает alias_method_chain в Ruby).

понедельник, 17 декабря 2018 г.

переменная errno в многопоточной программе

здравствуйте, допустим, в нескольких программных нитях(потоках) вызываем функцию read... и она завершается в одном из нитей, допустим, с errno = EAGAIN, в другой с errno = EBADF... потокобезопасна ли переменная errno, или в каждой нити она своя?


Ответ

Короткий ответ -- да, errno потокобезопасна. Это требование Posix. (смотри этот ответ)

вторник, 13 ноября 2018 г.

Где взять POSIX стандарт?

Хочу написать маленькую libc для своего микро-дистрибутива linux по POSIX стандарту, после гугления я понял, что его принимает IEEE, если нет, то поправите меня, ибо я не особо в этих стандартизациях разобрался.
На сайте IEEE платный.
Как писать по этому стандарту бесплатно, и где взять актуальную версию стандарта?


Ответ

некоторые важные версии публикуются для свободного доступа на сайте организации the open group
например:
The Single UNIX® Specification, Version 2 © 1997 The Open Group The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition © 2001-2004 The IEEE and The Open Group The Open Group Base Specifications Issue 7 IEEE Std 1003.1™, 2013 Edition © 2001-2013 The IEEE and The Open Group