всем привет! написал маленькую программку для знакомства с тредами в линуксе: Код (Text): #include <iostream> #include <pthread.h> #include <fcntl.h> #include <sys/sem.h> struct sembuf rel1 = {0, 1, 0}; struct sembuf cap1 = {0, -1, 0}; int sem1; char c; void* thread1_func(void* arg) { int fd = open("thr_file", O_WRONLY|O_CREAT, 0660); printf("check\n"); bool stop = false; while (!stop) { semop(sem1, &cap1, 1); printf("%c", c); if (c != '!') write(fd, &c, 1); else stop = true; semop(sem1, &rel1, 1); } close(fd); return NULL; } int main() { //int fd = open("/usr/lib/ooo-2.1/share/dict/ooo/th_en_US_v2.dat", O_RDONLY, 0660); int fd = open("thr.cpp", O_RDONLY, 0660); sem1 = semget(80, 1, O_CREAT); pthread_t thr1; pthread_attr_t attr1; pthread_attr_init(&attr1); int e = pthread_create(&thr1, &attr1, thread1_func, NULL); printf("%d--%d\n", thr1, e); while (read(fd, &c, 1)) { if (c == 'e' || c == 'y' || c == 'u' || c == 'i' || c == 'o' || c == 'a') { semop(sem1, &rel1, 1); semop(sem1, &cap1, 1); } } c = '!'; semop(sem1, &rel1, 1); semop(sem1, &cap1, 1); close(fd); return 0; } тред создаётся, но ничего не выполняет: Код (Text): [user@pluton-linux labs]$ g++ thr.cpp -o thr -pthread [user@pluton-linux labs]$ ./thr -1211630688--0 [user@pluton-linux labs]$ что ему не нравится? может я чего пропустил? зы. ось: Mandriva Linux release 2007.1 (Cooker) for i586 Kernel 2.6.17-13mdv on an i686
1. не надо смешивать System V IPC и POSIX IPC 2. где у тебя инициализация семафора? Код (Text): ... struct sembuf zero = {0, 0, 0}; ... /* инициализация семафора в 0 */ ... int e = pthread_create(&thr1, &attr1, thread1_func, NULL); ... while (read(fd, &c, 1)) { if (c == 'e' || c == 'y' || c == 'u' || c == 'i' || c == 'o' || c == 'a') { semop(sem1, &rel1, 1); semop(sem1, &zero, 1); } } + надо убрать Код (Text): semop(sem1, &rel1, 1); из thread1_func
в смысле посиксовые треды и system семафоры? до мьютексов я ещё не добрался. очень нужна? дефолтом ставятся нули и всё тут как тогда будет освобождаться семафор?
для портабельности обязательно некоторые системы не обнуляют значение семафора если начальное значение семафора 0 то после Код (Text): semop(sem1, &rel1, 1); в main() поток thread1_func сможет выполнить Код (Text): semop(sem1, &cap1, 1); а тем временем поток main() будет блокирован на операции Код (Text): semop(sem1, &zero, 1); в ожидании нуля когда thread1_func() выполнит декрементацию значения счетчика, поток main() разблокируется
да NPTL в Linux реадизован гораздо эффективнее System V IPC поэтому лучше для потоков пользоваться NPTL (Native Posix Threads Library)
это всё хорошо, но тред не выполняется над семафорами я подумаю желательно использовать mutex? библиотека pthread - это и есть NPTL? инициализация семафоров - с помощью semctl() ?
проверял прогу в ubuntu 7.10. немного её изменил. теперь main() создаёт два треда - первый записывает в файл, второй - считывает с файла. вобщем, аналог этой. первый тред один раз выполняется, и всё. дальше работает второй тред - правильно считывает. мне кажется, что они не переключаются. кто-то знает в чём дело, и как это исправить? Код (Text): #include <iostream> #include <pthread.h> #include <fcntl.h> #include <sys/sem.h> struct sembuf rel1 = {0, 1, 0}; struct sembuf cap1 = {0, -1, 0}; struct sembuf zero1 = {0, 0, 0}; int sem1; char c; void* thread1_func(void* arg) { printf("check\n"); int fd = open("thr_file", O_WRONLY|O_CREAT, 0660); bool stop = false; while (!stop) { printf("1111 "); semop(sem1, &cap1, 1); printf("222 "); printf("%c", c); if (c != '!') write(fd, &c, 1); else stop = true; //semop(sem1, &rel1, 1); } close(fd); return NULL; } void* thread2_func(void* arg) { int fd = open("thr.cpp", O_RDONLY, 0660); while (read(fd, &c, 1)) { //printf("%c* ", c); if (c == 'e' || c == 'y' || c == 'u' || c == 'i' || c == 'o' || c == 'a') { printf("%c* ", c); semop(sem1, &rel1, 1); //semop(sem1, &cap1, 1); semop(sem1, &zero1, 1); } } c = '!'; semop(sem1, &rel1, 1); //semop(sem1, &cap1, 1); semop(sem1, &zero1, 1); close(fd); return NULL; } int main() { //int fd = open("/usr/lib/ooo-2.1/share/dict/ooo/th_en_US_v2.dat", O_RDONLY, 0660); sem1 = semget(80, 1, O_CREAT); pthread_t thr1, thr2; pthread_attr_t attr; pthread_attr_init(&attr); int e = pthread_create(&thr1, &attr, thread1_func, NULL); printf("%u--%d\n", thr1, e); e = pthread_create(&thr2, &attr, thread2_func, NULL); printf("%u--%d\n", thr2, e); e = pthread_join(thr2, NULL); printf("%u\n", e); return 0; }
сделал туже прогу, только вместо семафоров использую сообщения: Код (Text): #include <iostream> #include <pthread.h> #include <fcntl.h> #include <errno.h> #include <sys/msg.h> #include <sys/ipc.h> struct msgbuff { long mtype; char data; }; void* thr1_func(void* arg) { int fd2 = open("thr2.out", O_CREAT | O_WRONLY, 0660); printf("fd=%u, err=%s\n",fd2, strerror(errno)); int mq; if ((mq = msgget(80, IPC_CREAT | IPC_EXCL | 0660)) == -1) { if (errno != EEXIST) { perror("msgget()"); return (void*)-1; } mq = msgget(80, 0); } printf("mq2=%u\n", mq); msgbuff mb = {0, 0}; while (mb.data != '!') { int r = msgrcv(mq, &mb, sizeof mb, 81, 0); //printf("r=%u d=%c, ", r, mb.data); int a=write(fd2, &mb.data, 1); printf("fd=%d, ", /*r, mb.data, */fd2); } printf("222\n"); printf("fd=%d", fd2); int r=close(fd2); printf("r=%d err=%s\n", r, strerror(errno)); return NULL; } int main() { pthread_t thr1; pthread_create(&thr1, NULL, thr1_func, NULL); int mq; if ((mq = msgget(80, IPC_CREAT | IPC_EXCL | 0660)) == -1) { if (errno != EEXIST) { perror("msgget()"); return -1; } mq = msgget(80, 0); } printf("mq1=%u\n", mq); int fd = open("thr2.cpp", O_RDONLY, 0660); char c; struct msgbuff mb; while (read(fd, &c, 1) != 0) { //printf("%c", c); printf("fd1=%d",fd); if (c == 'e' || c == 'y' || c == 'u' || c == 'i' || c == 'o' || c == 'a') { mb.mtype = 81; mb.data = c; msgsnd(mq, &mb, sizeof mb, 0); } } mb.mtype = 81; mb.data = '!'; msgsnd(mq, &mb, sizeof mb, 0); pthread_join(thr1, NULL); printf("111 fd=%d\n", fd); msgctl(mq, IPC_RMID, NULL); close(fd); return 0; } в конце main() стоит ожидание треда. интересно, что сначала выполняется весь main(), и только потом тред. почему не переключаются потоки? и ещё проблема: fd2 в треде меняется САМ. лог: Код (Text): [user@pluton-linux os]$ ./thr2 mq1=524288 fd1=3fd1=3fd1=3fd1=3 ... fd1=3fd1=3fd1=3fd=5, err=Success mq2=524288 fd=1777879268, fd=1979205860, fd=1710770404, fd=1777879268, fd=1878542564, fd=1710770404, fd=1643661540, fd=1777879268, fd=1979205860, fd=1710770404, fd=1710770404, fd=1643661540, fd=1777879268, fd=1979205860, fd=1710770404, fd=1777879268, fd=1979205860, fd=1710770404, fd=1710770404, fd=1878542564, fd=1777879268, fd=1979205860, fd=1710770404, fd=2046314724, fd=1777879268, fd=1979205860, fd=1710770404, fd=2046314724, fd=1777879268, fd=1979205860, fd=1979205860, fd=1878542564, fd=2046314724, fd=1710770404, fd=1643661540, fd=1643661540, fd=1643661540, fd=1878542564, fd=1777879268, fd=1979205860, fd=1878542564, fd=1777879268, fd=1643661540, fd=1777879268, fd=1878542564, fd=1710770404, fd=1878542564, fd=1979205860, fd=1777879268, fd=1979205860, fd=1710770404, fd=1710770404, fd=1878542564, fd=1710770404, fd=1878542564, fd=1777879268, fd=1777879268, fd=1710770404, fd=1777879268, fd=1710770404, fd=1878542564, fd=1710770404, fd=1878542564, fd=1710770404, fd=1710770404, fd=1979205860, fd=1878542564, fd=1777879268, fd=1710770404, fd=1777879268, fd=1979205860, fd=1979205860, fd=1777879268, fd=1710770404, fd=1643661540, fd=1643661540, fd=1777879268, fd=1777879268, fd=1710770404, fd=1878542564, fd=1777879268, fd=1979205860, fd=1643661540, fd=1643661540, fd=1777879268, fd=1643661540, fd=1777879268, fd=1710770404, fd=1643661540, fd=1643661540, fd=1777879268, fd=1643661540, fd=1643661540, fd=1777879268, fd=1777879268, fd=1777879268, fd=1878542564, fd=1710770404, fd=1777879268, fd=1710770404, fd=1710770404, fd=1878542564, fd=1710770404, fd=1878542564, fd=1710770404, fd=1979205860, fd=1777879268, fd=1643661540, fd=1777879268, fd=1710770404, fd=1643661540, fd=1710770404, fd=1643661540, fd=1710770404, fd=1643661540, fd=1710770404, fd=1979205860, fd=1777879268, fd=1777879268, fd=1710770404, fd=1777879268, fd=1710770404, fd=1878542564, fd=1710770404, fd=1878542564, fd=1710770404, fd=1710770404, fd=1979205860, fd=1710770404, fd=1777879268, fd=1979205860, fd=1777879268, fd=1878542564, fd=1710770404, fd=1643661540, fd=1979205860, fd=1979205860, fd=1777879268, fd=1710770404, fd=1710770404, fd=1643661540, fd=1777879268, fd=1777879268, fd=1777879268, fd=1710770404, fd=2046314724, fd=1979205860, fd=1777879268, fd=1878542564, fd=1643661540, fd=2046314724, fd=1710770404, fd=1643661540, fd=1643661540, fd=1777879268, fd=1710770404, fd=1878542564, fd=2046314724, fd=1710770404, fd=1643661540, fd=1643661540, fd=1777879268, fd=1710770404, fd=1878542564, fd=1710770404, fd=1643661540, fd=1878542564, fd=1777879268, fd=1777879268, fd=1878542564, fd=1710770404, fd=1710770404, fd=1979205860, fd=184043748, 222 fd=184043748r=-1 err=Bad file descriptor 111 fd=3
потому что так реализовано создание процессов через clone() вновь созданный процесс переходит в состояние TASK_RUNNING и помещается в текущую очередь выполнения (если нет привязки к определенному логическому процессору) в одну из очередей ожидающих выполнения процессов согласно его приоритету
rei3er, как я понимаю, логика потоков в том, что они выполняются в одном адресном пространстве «параллельно», то есть по маленьким кусочкам времени. как их заставить так работать?
видимый эффект последовательности может быть, но на самом деле это не так вот пример Код (Text): static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static void print(const char * str) { pthread_mutex_lock(&mutex); puts(str); pthread_mutex_unlock(&mutex); } static void * routine(void * arg) { while (1) print("thread"); } int main() { pthread_t thread; pthread_create(&thread, NULL, &routine, NULL); while (1) puts("main"); return 0; }
rei3er, я с этой прогой мучаюсь уже неделю. мне всегото надо в одном треде считать инфу, в другом записать только гласные. я уже запутался, пробовал с семафорами и сообщениями. даже на винде написал с семафорами, так там тоже глюки, символы пропадают