PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hilfe bei Threadprogrammierung in C++



Fischhirn
15-11-2010, 23:47
Hallo alle zusammen,

ich habe mich extra hier neu angemeldet, da ich trotz google Probleme in der Threadprogrammierung habe.
Genauer genommen liegt mein Problem aber eher in der Nutzung der Zeiger!
Ich habe ein Programm zur Ansteuerung des AVR-IO-NET-Moduls geschrieben und wenn ich alle Variablen global gestalte und dem Thread selber den nötigen Socket "einverleibe", funktioniert auch alles.

Aber naja.. globale Variablen sind unschön :rolleyes:

Ich habe nun das funktionierende so umgewurschtelt, wie es meiner Meinung nach vorerst richtig ist, nur das eben die entscheidenen Stellen fehlen.

Also wie kann ich im folgenden Quellcode den char Text aus Thread "abfrage" dem Thread "befehle" übergeben?
Und wie kann ich dem Thread "befehle" den Socket sock aus der main übergeben, um dem Modul die outputbefehle zu senden?



#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <termios.h>

using namespace std;
char buffersend[1024];

char outport11[] = "setport 1.1\r\n";
char outport10[] = "setport 1.0\r\n";

char outport21[] = "setport 2.1\r\n";
char outport20[] = "setport 2.0\r\n";

char outport31[] = "setport 3.1\r\n";
char outport30[] = "setport 3.0\r\n";

char outport41[] = "setport 4.1\r\n";
char outport40[] = "setport 4.0\r\n";

char outport51[] = "setport 5.1\r\n";
char outport50[] = "setport 5.0\r\n";

char outport61[] = "setport 6.1\r\n";
char outport60[] = "setport 6.0\r\n";

char outport71[] = "setport 7.1\r\n";
char outport70[] = "setport 7.0\r\n";

char outport81[] = "setport 8.1\r\n";
char outport80[] = "setport 8.0\r\n";



int kbhit(void);

int kbhit(void)
{
struct termios term, oterm;
int fd = 0;
int c = 0;
tcgetattr(fd, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);
c = getchar();
tcsetattr(fd, TCSANOW, &oterm);
if (c != -1)
ungetc(c, stdin);
return ((c != -1) ? 1 : 0);
}

int getch();

int getch()
{
static int ch = -1, fd = 0;
struct termios neu, alt;
fd = fileno(stdin);
tcgetattr(fd, &alt);
neu = alt;
neu.c_lflag &= ~(ICANON|ECHO);
tcsetattr(fd, TCSANOW, &neu);
ch = getchar();
tcsetattr(fd, TCSANOW, &alt);
return ch;
}

void *abfrage()
{
cout << "Thread abfrage gestartet!\n";
char text = 'x';

while(text != 'q')
{
if(kbhit())
{
text = getchar();
}
else
{
text = 'x'
}
}
return 0;
}

void *befehle()
{
cout << "Thread befehle gestartet!\n";
while(text != 'q')
{
if (text != 'x')
{

if(text == '1')
{
send(sock, outport11, strlen(outport11), 0);
}
if(text == '2')
{
send(sock, outport21, strlen(outport21), 0);
}
if(text == '3')
{
send(sock, outport31, strlen(outport31), 0);
}
if(text == '4')
{
send(sock, outport41, strlen(outport41), 0);
}
if(text == '5')
{
send(sock, outport51, strlen(outport51), 0);
}
if(text == '6')
{
send(sock, outport61, strlen(outport61), 0);
}
if(text == '7')
{
send(sock, outport71, strlen(outport71), 0);
}
if(text == '8')
{
send(sock, outport81, strlen(outport81), 0);
}
}
else
{
send(sock, outport10, strlen(outport10), 0);
usleep(3000);
send(sock, outport20, strlen(outport20), 0);
usleep(3000);
send(sock, outport30, strlen(outport30), 0);
usleep(3000);
send(sock, outport40, strlen(outport40), 0);
usleep(3000);
send(sock, outport50, strlen(outport50), 0);
usleep(3000);
send(sock, outport60, strlen(outport60), 0);
usleep(3000);
send(sock, outport70, strlen(outport70), 0);
usleep(3000);
send(sock, outport80, strlen(outport80), 0);
}
}
return 0;
}

int main()
{
sockaddr_in myaddr;
int sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
cout << "Fehler beim Erzeugen des Sockets\n";
}
cout <<"Socket erzeugt!\n";
bzero(&myaddr, sizeof(myaddr));
myaddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.178.101", &myaddr.sin_addr);
myaddr.sin_port = htons(50290);

if(connect(sock, (struct sockaddr *)&myaddr, sizeof(myaddr))<0)
{
cout << "Fehler beim Verbinden!\n";
}
else
{
cout << "Mit AVR-IO-NET verbunden!\n";
}

pthread_t p1,p2;
pthread_create (&p1, NULL, abfrage, NULL);
pthread_create (&p2, NULL, befehle, NULL);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
cout << "Programm Ende \n";
}


Und falls es noch hilft, hier die Fehlermeldung die logischerweise noch kommt:


test.c: In function ‘void* abfrage()’:
test.c:91: error: expected ‘;’ before ‘}’ token
test.c: In function ‘void* befehle()’:
test.c:99: error: ‘text’ was not declared in this scope
test.c:104: error: ‘sock’ was not declared in this scope
test.c:108: error: ‘sock’ was not declared in this scope
test.c:112: error: ‘sock’ was not declared in this scope
test.c:116: error: ‘sock’ was not declared in this scope
test.c:120: error: ‘sock’ was not declared in this scope
test.c:124: error: ‘sock’ was not declared in this scope
test.c:128: error: ‘sock’ was not declared in this scope
test.c:132: error: ‘sock’ was not declared in this scope
test.c:137: error: ‘sock’ was not declared in this scope
test.c: In function ‘int main()’:
test.c:180: error: invalid conversion from ‘void* (*)()’ to ‘void* (*)(void*)’
test.c:180: error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’
test.c:181: error: invalid conversion from ‘void* (*)()’ to ‘void* (*)(void*)’
test.c:181: error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’


Ich schreibe alles unter Linux (Ubuntu) und benutze bis jetzt den g++ compiler.
Naja da haperts echt bei mir und ich hoffe ihr könnt mir helfen :)

dml
16-11-2010, 16:01
Deine beiden Zauberwörter heissen PassByReference und PassByValue. :)
Wenn Du eine Funktion entwickelst kennt diese Funktion keine Variablen von auserhalb dieser Funktion. Deshalb musst Du die benötigten Variablen als Parametern der Funktion übergeben. Dabei ist darauf zu achten, ob du dabei die Variable auserhalb auch verändern (PassByReference) möchtest oder nur die Werte (PassByValue). Zu beachten dabei ist das die Methoden einer Klasse die Variablen der Klasse auch ohne Parameterübergabe kennt.


PassByValue( int n, string c, int feld[2], Klasse Kl, Klasse pKl)
PassByReference( int &n, string *c, int feld[2], Klasse &Kl, Klasse *pKl){
Wie Du schnell erkennen kannst, nimmt PassByReference in Gegensatz zu PassByValue die Adresse der Variable auf und kann Sie so umändern.


Für Deine Funktion:

void *befehle()
müsste also

static void befehle( int &sock, string outport[] ){
...
return(void) pthread_self(); oder
pthread_exit((*void) pthread_self());
}
Arrays Aufgrund ihrer Beschaffenheit übergeben Werte immer als PassByReference.

Also genau wie bei pthread_create (&p2, NULL, &befehle, NULL); :)

Fischhirn
16-11-2010, 17:31
Vielen Dank schonmal!

PassByReference und PassByValue waren mir als Anfänger noch gar nicht geläufig.
Ich habe jetzt den Code von dir mit eingefügt und er meckert auch nun nicht mehr, das er "sock" in befehle nicht kennt.

Leider versteh ich immer noch nicht was ich hier machen muss:


pthread_t p1,p2;
//pthread_create (&p1, NULL, abfrage, NULL);
pthread_create (&p2, NULL, befehle, NULL);
//pthread_join (p1, NULL);
pthread_join (p2, NULL);

rechts neben "befehle" müsste statt einer NULL, ja der sock stehen richtig?
Aber egal was ich mache, er meckert leider immer wieder:


test.c: In function ‘int main()’:
test.c:184: error: invalid conversion from ‘void (*)(int&, char&)’ to ‘void* (*)(void*)’
test.c:184: error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’


Ich kann aus dem socket ja nicht irgendwas anderes zaubern, deswegen versteh ich den nötigen Schirtt einfach nicht, damit es mit pthread_create auch funktioniert :(

dml
17-11-2010, 09:38
Versuch mal : pthread_create (&p2, NULL, &befehle, NULL);
müsste eigentlich funktionieren.

Ach Mist, glaube er will das Du nur:


static void befehle( void* arg ){
...
return(void) pthread_self(); oder
pthread_exit((*void) pthread_self());
}

übergibst.
....



// Also, Du erstellst ein struct in den Du alles wichtige hineipacken kannst.
struct data {
int wert;
char msg[BUF];
};

// Dann erstellst Du in Deiner main ein struct:
int main (void) {
struct data *f = (struct data *)malloc(sizeof(struct data));
// Füllst die Werte des structes und
pthread_create (&p2, NULL, &befehle, NULL);
}

Quelle: "Linux-UNIX Programmierung" von Jürgen Wolf; Galileo Computing Verlag

Fischhirn
17-11-2010, 17:04
Danke nochmal!

Aber so ganz versteh ichs nicht..
Wenn ich ein Struct data erstelle, um dort Variablen zu definieren und dann mit "data arg;" eben arg erstelle, was bringts mir dann überall z.b. mit "arg.sock"
auf meinen socket zuzugreifen? Dann kann ich ja gleich alles global machen.. es erspart mir ja keine Arbeit, sondern ich muss nur noch mehr tippen?

Denke aber mal ich habs einfach nicht verstanden, aber ich komme einfach nicht weiter.


#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <termios.h>

using namespace std;
char buffersend[1024];

char outport11[] = "setport 1.1\r\n";
char outport10[] = "setport 1.0\r\n";

char outport21[] = "setport 2.1\r\n";
char outport20[] = "setport 2.0\r\n";

char outport31[] = "setport 3.1\r\n";
char outport30[] = "setport 3.0\r\n";

char outport41[] = "setport 4.1\r\n";
char outport40[] = "setport 4.0\r\n";

char outport51[] = "setport 5.1\r\n";
char outport50[] = "setport 5.0\r\n";

char outport61[] = "setport 6.1\r\n";
char outport60[] = "setport 6.0\r\n";

char outport71[] = "setport 7.1\r\n";
char outport70[] = "setport 7.0\r\n";

char outport81[] = "setport 8.1\r\n";
char outport80[] = "setport 8.0\r\n";

struct data
{
int sock;
char text;
};





int kbhit(void);

int kbhit(void)
{
struct termios term, oterm;
int fd = 0;
int c = 0;
tcgetattr(fd, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);
c = getchar();
tcsetattr(fd, TCSANOW, &oterm);
if (c != -1)
ungetc(c, stdin);
return ((c != -1) ? 1 : 0);
}

int getch();

int getch()
{
static int ch = -1, fd = 0;
struct termios neu, alt;
fd = fileno(stdin);
tcgetattr(fd, &alt);
neu = alt;
neu.c_lflag &= ~(ICANON|ECHO);
tcsetattr(fd, TCSANOW, &neu);
ch = getchar();
tcsetattr(fd, TCSANOW, &alt);
return ch;
}

void* abfrage(void* arg)
{
cout << "Thread abfrage gestartet!\n";

while(arg.text != 'q')
{

if(kbhit())
{
arg.text = getchar();
}
else
{
arg.text = 'x';
}
}
return(void) pthread_self();
}

void* befehle(void* arg)
{
cout << "Thread befehle gestartet!\n";
while(arg.text != 'q')
{
if (arg.text != 'x')
{

if(arg.text == '1')
{
send(arg.sock, outport11, strlen(outport11), 0);
}
if(text == '2')
{
send(arg.sock, outport21, strlen(outport21), 0);
}
if(text == '3')
{
send(arg.sock, outport31, strlen(outport31), 0);
}
if(text == '4')
{
send(arg.sock, outport41, strlen(outport41), 0);
}
if(text == '5')
{
send(arg.sock, outport51, strlen(outport51), 0);
}
if(text == '6')
{
send(arg.sock, outport61, strlen(outport61), 0);
}
if(text == '7')
{
send(arg.sock, outport71, strlen(outport71), 0);
}
if(text == '8')
{
send(arg.sock, outport81, strlen(outport81), 0);
}
}
else
{
send(arg.sock, outport10, strlen(outport10), 0);
usleep(3000);
send(arg.sock, outport20, strlen(outport20), 0);
usleep(3000);
send(arg.sock, outport30, strlen(outport30), 0);
usleep(3000);
send(arg.sock, outport40, strlen(outport40), 0);
usleep(3000);
send(arg.sock, outport50, strlen(outport50), 0);
usleep(3000);
send(arg.sock, outport60, strlen(outport60), 0);
usleep(3000);
send(arg.sock, outport70, strlen(outport70), 0);
usleep(3000);
send(arg.sock, outport80, strlen(outport80), 0);
}
}
return(void) pthread_self();
}

int main()
{
struct data *arg = (struct data *)malloc(sizeof(struct data));
arg.text= 'x';
arg.sock = socket (AF_INET, SOCK_STREAM, 0);

sockaddr_in myaddr;
if (arg.sock < 0)
{
cout << "Fehler beim Erzeugen des Sockets\n";
}
cout <<"Socket erzeugt!\n";
bzero(&myaddr, sizeof(myaddr));
myaddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.178.101", &myaddr.sin_addr);
myaddr.sin_port = htons(50290);

if(connect(arg.sock, (struct sockaddr *)&myaddr, sizeof(myaddr))<0)
{
cout << "Fehler beim Verbinden!\n";
}
else
{
cout << "Mit AVR-IO-NET verbunden!\n";
}

pthread_t p1,p2;
pthread_create (&p1, NULL, &abfrage,(void*) &arg);
pthread_create (&p2, NULL, &befehle,(void*) &arg);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
cout << "Programm Ende \n";

Fehlercode:

test.c: In function ‘void* abfrage(void*)’:
test.c:89: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:94: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:98: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:101: error: void value not ignored as it ought to be
test.c: In function ‘void* befehle(void*)’:
test.c:107: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:109: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:112: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘void*’
test.c:114: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:116: error: ‘text’ was not declared in this scope
test.c:118: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:120: error: ‘text’ was not declared in this scope
test.c:122: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:124: error: ‘text’ was not declared in this scope
test.c:126: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:128: error: ‘text’ was not declared in this scope
test.c:130: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:132: error: ‘text’ was not declared in this scope
test.c:134: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:136: error: ‘text’ was not declared in this scope
test.c:138: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:140: error: ‘text’ was not declared in this scope
test.c:142: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:147: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:149: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:151: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:153: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:155: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:157: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:159: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:161: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘void*’
test.c:164: error: void value not ignored as it ought to be
test.c: In function ‘int main()’:
test.c:170: error: request for member ‘text’ in ‘arg’, which is of non-class type ‘data*’
test.c:171: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘data*’
test.c:174: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘data*’
test.c:184: error: request for member ‘sock’ in ‘arg’, which is of non-class type ‘data*’

dml
17-11-2010, 19:16
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <termios.h>

using namespace std;
char buffersend[1024];

char outport11[] = "setport 1.1\r\n";
char outport10[] = "setport 1.0\r\n";

char outport21[] = "setport 2.1\r\n";
char outport20[] = "setport 2.0\r\n";

char outport31[] = "setport 3.1\r\n";
char outport30[] = "setport 3.0\r\n";

char outport41[] = "setport 4.1\r\n";
char outport40[] = "setport 4.0\r\n";

char outport51[] = "setport 5.1\r\n";
char outport50[] = "setport 5.0\r\n";

char outport61[] = "setport 6.1\r\n";
char outport60[] = "setport 6.0\r\n";

char outport71[] = "setport 7.1\r\n";
char outport70[] = "setport 7.0\r\n";

char outport81[] = "setport 8.1\r\n";
char outport80[] = "setport 8.0\r\n";

struct data
{
int sock;
char text[255];
};





int kbhit(void);

int kbhit(void)
{
struct termios term, oterm;
int fd = 0;
int c = 0;
tcgetattr(fd, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);
c = getchar();
tcsetattr(fd, TCSANOW, &oterm);
if (c != -1)
ungetc(c, stdin);
return ((c != -1) ? 1 : 0);
}

int getch();

int getch()
{
static int ch = -1, fd = 0;
struct termios neu, alt;
fd = fileno(stdin);
tcgetattr(fd, &alt);
neu = alt;
neu.c_lflag &= ~(ICANON|ECHO);
tcsetattr(fd, TCSANOW, &neu);
ch = getchar();
tcsetattr(fd, TCSANOW, &alt);
return ch;
}

static void* abfrage(void* arg)
{
struct data *f = (struct data*)arg;
cout << "Thread abfrage gestartet!\n";

while(f->text != "q")
{

if(kbhit())
{
f->text = getchar();
}
else
{
f->text = "x";
}
}
return(void) pthread_self();
}

static void* befehle(void* arg)
{
struct data *f = (struct data*)arg;
cout << "Thread befehle gestartet!\n";
while(f->text != "q")
{
if (f->text != "x")
{

if(f->text == "1")
{
send(f->sock, outport11, strlen(outport11), 0);
}
if(f->text == "2")
{
send(f->sock, outport21, strlen(outport21), 0);
}
if(f->text == "3")
{
send(f->sock, outport31, strlen(outport31), 0);
}
if(f->text == "4")
{
send(f->sock, outport41, strlen(outport41), 0);
}
if(f->text == "5")
{
send(f->sock, outport51, strlen(outport51), 0);
}
if(f->text == "6")
{
send(f->sock, outport61, strlen(outport61), 0);
}
if(f->text == "7")
{
send(f->sock, outport71, strlen(outport71), 0);
}
if(f->text == "8")
{
send(f->sock, outport81, strlen(outport81), 0);
}
}
else
{
send(f->sock, outport10, strlen(outport10), 0);
usleep(3000);
send(f->sock, outport20, strlen(outport20), 0);
usleep(3000);
send(f->sock, outport30, strlen(outport30), 0);
usleep(3000);
send(f->sock, outport40, strlen(outport40), 0);
usleep(3000);
send(f->sock, outport50, strlen(outport50), 0);
usleep(3000);
send(f->sock, outport60, strlen(outport60), 0);
usleep(3000);
send(f->sock, outport70, strlen(outport70), 0);
usleep(3000);
send(f->sock, outport80, strlen(outport80), 0);
}
}
return(void) pthread_self();
}

int main()
{
sockaddr_in myaddr;
int sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
cout << "Fehler beim Erzeugen des Sockets\n";
}
cout <<"Socket erzeugt!\n";



struct data *f = (struct data *)malloc(sizeof(struct data));
f->sock = sock;
f->text= "x";

if (f->sock < 0)
{
cout << "Fehler beim Erzeugen des Sockets\n";
}
cout <<"Socket erzeugt!\n";
bzero(&myaddr, sizeof(myaddr));
myaddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.178.101", &myaddr.sin_addr);
myaddr.sin_port = htons(50290);

if(connect(f->sock, (struct sockaddr *)&myaddr, sizeof(myaddr))<0)
{
cout << "Fehler beim Verbinden!\n";
}
else
{
cout << "Mit AVR-IO-NET verbunden!\n";
}

pthread_t p1,p2;
pthread_create (&p1, NULL, &abfrage,f);
pthread_create (&p2, NULL, &befehle,f);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
cout << "Programm Ende \n";

Pi * Daumen müsste das Funktionieren, habe jetzt aber nicht nach inhaltlicher Korrektheit geachtet.
Viel Spaß!