Even though this isn't relevant to the group, here are a couple of
examples that may help.
It's a client-server program, well documented.
mike wrote:
Hi,
I am having difficulty in creating a thread using pthread_create. It
seems that pthread_create does not execute 'program', and returns -1;
I have checked the API but I am not sure why this isn't working.
#include <stdio.h>
#include <pthread.h>
void *program(void *param)
{ char* word = (char*)param;
printf("%s\n", word);
return;
}
int main()
{ int state;
void* program(void*);
pthread_t tid;
char word[] = "word";
state = pthread_create(&tid, NULL, program, (void*)word);
printf("state is: %d", state);
}
/*1************************************************ *************************/
/* */
/* Author: PUSHKAR S. PRADHAN */
/* CS6733 - Spring 2001 */
/* Section - 2 */
/* HomeWork 2 */
/* File Name: pradhan-server.cpp */
/* Description: Implements server which listens for file request from */
/* clients. It reads in the file and sends it to the client in parts. */
/************************************************** ************************/
#include <errno.h> // print error no.
#include <fcntl.h> // for open
#include <iostream.h> // cin/cout
#include <pthread.h> // pthread functions
#include <signal.h> // handle signals
#include <siginfo.h> // print signal info.
#include <stdio.h> // perror
#include <string.h> // strcpy, memset
#include <sys/ipc.h> // IPC_CREAT, IPC_NOWAIT
#include <sys/msg.h> // message queues
#include <sys/types.h> // key_t
#include <unistd.h> // getpid, read
using namespace std;
#define NUM_THREADS 5 // max. no. of threads
#define MSGSZ 128 // max. message size
#define VALID 1 // flags for filbuf structure
#define INVALID 0
// Declare the message structure.
typedef struct mesgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
typedef struct filbuf {
long mtype;
long valid;
long mlength;
char mtext[MSGSZ];
} file_buf;
void cleanUp(int sig);
void *opFile(void *arg[]); // thread routine
int main () {
int i;
int msqid;
int msgflg = IPC_CREAT | 0666;
pid_t serverPid;
key_t key;
size_t buf_length;
pthread_t tid[NUM_THREADS]; // array of thread IDs
// Use the current process PID to create
// the message queue id for the server
// Also print out the process PID to
// pass it on the commandline to the client
serverPid = getpid();
cout << "process pid: " << serverPid << endl;
key = (int)serverPid;
if ((msqid = msgget(key, msgflg)) < 0) {
perror("server: msgget error:");
cout << msqid << endl;
exit(-1);
}
// server must be killed explicitly using ^C
if( signal(SIGINT, cleanUp) == SIG_ERR) {
perror("server: signal:");
exit(-1);
}
while(1)
{
// create threads
for ( i = 0; i < NUM_THREADS; i++) {
int ret = pthread_create(&tid[i], NULL, opFile, (void *)NULL);
if (ret != 0) {
perror("server: Thread creation error:");
exit(-1);
}
}
// wait for them to complete
for ( i = 0; i < NUM_THREADS; i++) {
if(pthread_join(tid[i], NULL) != 0)
exit(-1);
}
}
} // end of main
/************************************************** **************************/
/* Function to fetch requested file */
/************************************************** **************************/
void *opFile(void *arg[]) {
pid_t x;
key_t tempKey;
key_t key1;
size_t buf_length;
file_buf sbuf; // send file contents
message_buf rbuf; // recv file name and client PID
int i;
int msqid_1;
int msqid_2;
int fs; // file des. for file
char buffer[MSGSZ]; // to read file contents
char fileName[MSGSZ]; // to get requested file name
// set buffer contents to NULL
for(int i = 0; i < MSGSZ; i++) {
memset(&rbuf.mtext[i], '\0', sizeof(char));
memset(&sbuf.mtext[i], '\0', sizeof(char));
}
// connect to the msg. que. created by the server
// to recv file requests
x = getpid();
key1 = (int)x;
if ((msqid_1 = msgget(key1, 0666)) < 0) {
cout << pthread_self() << endl;
perror("server: opFile: msgget:");
cout << msqid_1 << endl;
pthread_exit(NULL);
}
// Recv mesg. of type 1 in rbuf
int bytRecv = msgrcv(msqid_1, &rbuf, MSGSZ, 1, 0);
if(bytRecv < 0) {
cout << pthread_self() << endl;
perror("server: opFile: msgrcv error:");
pthread_exit(NULL);
}
// decode message
int index = 0;
memcpy(&x, (char *)&rbuf.mtext[index], sizeof(x));
index += sizeof(x);
// file name
i = 0;
for(;;) {
fileName[i] = (char)rbuf.mtext[index];
i++;
index++;
if(fileName[i-1] == '\0')
break;
}
cout << "server: opFile: client pid: " << x;
cout << ", File requested: " << fileName << endl;
// connect to the mesg. que. created by the client
// to recv. file contents
tempKey = (int)x;
if ((msqid_2 = msgget(tempKey, 0666)) < 0) {
perror("server: opFile: msgget:");
pthread_exit(NULL);
}
// open file whose contents must be
// sent to the client
if ( (fs = open(fileName, O_RDONLY)) < 0) {
perror("server: opFile: File open error:");
// send a mesg. to the client to inform it
// about this situation
sbuf.mtype = 2;
sbuf.valid = INVALID;
sbuf.mlength = sizeof(sbuf.mlength) + sizeof(sbuf.valid);
buf_length = sizeof(sbuf.mlength) + sizeof(sbuf.valid);
// strncpy(sbuf.mtext, buffer, n);
if (msgsnd(msqid_2, &sbuf, buf_length, 0) < 0)
perror("server: opFile: msgsnd:");
pthread_exit(NULL);
}
// read file contents into a buffer and send them to
// the message que. (created for this) of the client
int n;
while ( (n = read(fs, buffer, sizeof(buffer))) != 0)
{
if (n < 0)
{
perror("server: opFile: Read error:");
pthread_exit(NULL);
}
else
{
sbuf.mtype = 2;
sbuf.valid = VALID;
sbuf.mlength = n + sizeof(sbuf.mlength) + sizeof(sbuf.valid);
strncpy(sbuf.mtext, buffer, n);
buf_length = n + sizeof(sbuf.mlength) + sizeof(sbuf.valid);
// Send file contents until EOF is reached
if (msgsnd(msqid_2, &sbuf, buf_length, 0) < 0) {
perror("server: opFile: msgsnd:");
pthread_exit(NULL);
}
}
}
// send zero length mesg., EOF has been reached
sbuf.mtype = 2;
sbuf.valid = VALID;
sbuf.mlength = sizeof(sbuf.mlength) + sizeof(sbuf.valid);
buf_length = n + sizeof(sbuf.mlength) + sizeof(sbuf.valid);
// For this mesg. the contents are not important
if (msgsnd(msqid_2, &sbuf, buf_length, 0) < 0) {
perror("server: opFile: msgsnd:");
pthread_exit(NULL);
}
return (NULL);
} // function opFile ends
/************************************************** **************************/
/* Function to remove message queue */
/************************************************** **************************/
void cleanUp(int sig) {
int msqid;
pid_t temp = getpid();
key_t key = (int)temp;
psignal(sig, "Received signal:"); // print recv. signal
// connect to the mesg. queue
if ((msqid = msgget(key, 0666)) < 0) {
perror("server: cleanUp: msgget:");
cout << msqid << endl;
exit(-1);
}
// Remove the message queue
if (msgctl(msqid, IPC_RMID, 0) < 0) {
perror("server: cleanUp: msgctl:");
exit(-1);
}
exit(0);
} // function cleanUp ends
/************************************************** ************************/
/* */
/* Author: PUSHKAR S. PRADHAN */
/* CS6733 - Spring 2001 */
/* Section - 2 */
/* HomeWork 2 */
/* File Name: pradhan-client.cpp */
/* Description: This is the client, which requests a file's contents. */
/* The server sends the contents in parts and the client prints them */
/* to the standard output. */
/* The server PID (message queue ID) and the filename are the command */
/* line arguments for this program. */
/************************************************** ************************/
#include <errno.h> // print error no.
#include <iostream.h> // standard output
#include <stdio.h> // perror
#include <stdlib.h> // atoi
#include <string.h> // memset
#include <sys/ipc.h> // IPC_CREAT, IPC_NOWAIT
#include <sys/msg.h> // msgsnd
#include <unistd.h> // getpid
using namespace std;
#define MSGSZ 128 // max. mesg. size
#define VALID 1 // flags for filbuf structure
#define INVALID 0
// Declare the message structures.
typedef struct mesgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
typedef struct filbuf {
long mtype;
long valid;
long mlength;
char mtext[MSGSZ];
} file_buf;
int main (int argc, char * argv[]) {
int msqid_1; // to send filename
int msqid_2; // to recv contents
int msgflg = IPC_CREAT | 0666;
pid_t clientPid;
key_t key1;
key_t key2;
message_buf sbuf; // to send file name
file_buf rbuf; // to recv file contents
size_t buf_length;
if (argc != 3) {
// check for valid arguments
cout << "Usage: " << argv[0];
cout << " <server PID> <filename> " << endl;
exit(-1);
}
clientPid = getpid(); // get pid of current process
cout << "client pid: " << clientPid << endl;
// create a separate message queue to recv.
// the file contents from the server
// Use the current process PID for the
// msg. queue id
key2 = (int)clientPid;
if ((msqid_2 = msgget(key2, msgflg)) < 0) {
perror("client: msgget:");
exit(-1);
}
// connect to mesg. que. created by server
key1 = atoi(argv[1]);
if ((msqid_1 = msgget(key1, 0666)) < 0) {
perror("client: msgget:");
cout << msqid_1 << endl;
exit(-1);
}
// set buffer contents to NULL
for(int i = 0; i < MSGSZ; i++)
memset(&sbuf.mtext[i], '\0', sizeof(char));
// create message with client's PID (msg. key)
// and requested filename
sbuf.mtype = 1;
int index = 0;
memcpy(&sbuf.mtext[index], (char *)&clientPid, sizeof(clientPid));
index += sizeof(clientPid);
memcpy(&sbuf.mtext[index], argv[2], strlen(argv[2])+1);
index = index + (strlen(argv[2]) + 1);
buf_length = index;
// Send a message of type 1
if (msgsnd(msqid_1, &sbuf, buf_length, 0) < 0) {
cout << "msgsend: " << msqid_1 << " " << sbuf.mtype << " " <<
sbuf.mtext << "" << buf_length << endl;
perror("client: msgsnd:");
exit(-1);
}
else
cout << "File request sent" << endl;
// o/p contents to terminal
cout << argv[2] << ":" << endl;
// Receive a message of type 2 in rbuf
for(;;) {
int bytRecv = msgrcv(msqid_2, &rbuf,
(MSGSZ+sizeof(rbuf.mlength)+sizeof(rbuf.valid)),
2, 0);
if(bytRecv < 0) {
perror("client: msgrcv error:");
exit(-1);
}
if(rbuf.mlength == sizeof(rbuf.mlength) + sizeof(rbuf.valid)) {
if(rbuf.valid == INVALID)
cout << "no such file" << endl;
else {} // end of file is reached
break;
}
for(int i = 0; i < (bytRecv-sizeof(rbuf.mlength)-sizeof(rbuf.valid)); i++)
cout << rbuf.mtext[i];
}
// Remove the message queue
if (msgctl(msqid_2,IPC_RMID,0) < 0) {
perror("client: msgctl:");
exit(-1);
}
} // end of main