I'm having problems passing a string to a thread function using pthread_create
I get strange charactes when i run the progam
here is the code
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#define NTHREADS 3
void *myFun(void *ptr){
char * string;
string = (char *) ptr;
printf("string: %s\n", string);
return NULL;
}
int main(int argc, char *argv[]){
pthread_t threads[NTHREADS];
char* thread_args[NTHREADS];
int i;
char* string;
/* spawn threads */
for (i=0; i<NTHREADS; ++i){
string = "file1.txt";
thread_args[i] = string;
if(pthread_create(&threads[i], NULL, myFun, (void *) &thread_args[i]) != 0){
printf("Error creating thread\n");
exit(1);
}
}
/* Wait for threads to finish */
for (i=0; i<NTHREADS; ++i) {
pthread_join(threads[i], NULL);
}
return 0;
}
I can pass a int without problems doing a cast to int in the same way i did in the code, but with char it is not working.
Pass the pointer, not the address of the pointer.
if(pthread_create(&threads[i], NULL, myFun, (void *) thread_args[i])
^
Related
Here is my code I tried also to do casting in mmap but it didn't work.
I need that after I use in memcpy *src include array of the shared from integer type and that printf print array of integer(the pid in code). with %d in printf the code not compile and when I use 5p its print me hexadecimal address
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char const *argv[])
{
int shared[3];
void* src = mmap(0,num, PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_SHARED, fd, 0);
if (src == MAP_FAILED)
{
fprintf(stderr, "mmap() failed\n");
exit(EXIT_FAILURE);
}
//placement of shared array and print
for(int i = 0; i < num; i++)
{
if ((pid = fork()) < 0)
{
perror("fork error\n");
}
else
{
//Placement of pid to shared array
shared[i]=getpid();
}
//need to change the permission in map, create a virtual memory
}
memcpy(src,shared, num+1);
printf("%d\n",src);
close(fd);
return 0;
}
//trying to make each thread print its thread number not id and then print a message from the array would like to be able to pass array in pthread create but right now I am getting a an error array subscript is not an integer please help me
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
void * print_funtion( void* i, void* message)
{
printf("Thread %d: ",(int*) i);
printf("Thread %s: ", message);
return NULL;
}
int main(int argc, char* argv[]){
int i;
int num = atoi(argv[1]);
//printf("%d \n", num);
for(i = 1; i <= num; i++)
{
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
//printf("%d \n", i);
pthread_t tid;
pthread_create(&tid, NULL, print_funtion,(void*)i, (void*)messages[i]);
pthread_join(tid,NULL);
}
return 0;
}
There are many problems in the code and I'll point them out individually as comments:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
// Note: In most cases, you should use (char *) for strings instead of char[XX].
// Note: You don't need to set the number of elements in the array
// because it is automatically inferred from the initializer.
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
void *print_function(void *data)
{
// The data you passed is int not a pointer to int.
int i = (int)data;
printf("Thread %d: \n", i);
// You need to use %s for printing string.
printf("Message: %s\n", messages[i]);
return NULL;
}
int main(int argc, char* argv[])
{
int i;
int num = atoi(argv[1]);
// Limit the number of running threads so you don't slow down you computer (10 is already too much. It depends on the number of cores you CPU has).
#define MAX_NUM_OF_THREADS 10
if(num > MAX_NUM_OF_THREADS)
num = MAX_NUM_OF_THREADS;
// I explain why we need to store the thread ids down below.
pthread_t thread_ids[MAX_NUM_OF_THREADS];
for(i = 0; i < num; i++)
{
pthread_t tid;
void *thread_data = (void *)(i + 1);
pthread_create(&tid, NULL, print_function, thread_data);
thread_ids[i] = tid;
}
// You can't join with the thread in the previous loop because it will serialize thread creation.
// Meaning the program will not create the next thread before the current thread finish execution.
// Instead, you need to create all the threads first then you join to them one by one afterward.
// And for that you need to store the thread ids for each thread in order to join with them after they are created.
for(i = 0; i < num; i++)
{
pthread_join(thread_ids[i], NULL);
}
return 0;
}
I'm writing some code for a project and I have an issue when I try to update an area of shared memory with another process.
Basically one process create a shared memory, then it creates one child that, using execve, execute a process the aim of which is to update that shared memory knowing its key.
At the end the main process prints all the datas from the shm to stdout.
At that point I have noticed that shm has not been updated.
I can't understand why. I've tried with regular assignment (=) or assigning every field with a function (updatef), but it doesn't work.
(Of course in the real program I used semaphores to regulate the access to shm, i wrote this code to minimize the code to see the problem)
Process t:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
Process u:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr[i], p);
}
shmdt(addr);
return 0;
}
Short answer is of course passing pointer instead of value and that'll do
updatef(&arr[i], p);
Long answer lies in pass by value and pass by reference, when updatef is called with addr[i] as in
updatef(arr[i], p);
essentially the value is copied to calling function and never gets reflected to attached pointer viz addr as a result the original addr pointer get unchanged on the other hand when we pass the address like
updatef(&addr[i], p);
//or
updatef(addr+i, p);
reference is passed which inturn will update the contents pointed to by addr+i pointer
to add on IMO splitting the code will make this more presentable and readable and maintainable and bla bla bla here is a bit
File 1 - s.h, keep shared and global data here
#ifndef S_H_INCLUDED
#define S_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome; };
#endif
t.c
#include "s.h" // include global header here
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
u.c
#include "s.h" // common included here
static void updatef(struct pdata *a, struct pdata p){
a->ppid = p.ppid;
a->ptype = p.ptype;
strcpy(a->pname, p.pname);
a->pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr+i, p);
}
shmdt(addr);
return 0;
}
and the final build step
gcc t.c -o t
gcc u.c -o u
I'm supposed to write a program which creates 2 processes, connects between them with a pipe, and after a given time will end both processes and terminate.
one of the programs will write to the pipe, and the other will read from it and print it to STDOUT.
the reading process will be called first, then the pid will be passed to the second process so it will give SIGUSR1 signals to the first process, to tell it to read.
for some reason i never see the output in the terminal of the first process,
further more, it doesn't even print the line:"trying to exec1\n" which is where i call "execlp" for the process that prints.
here is the code for the 3 programs:
the main program:
#define STDERR 2
#define STDOUT 1
#define STDIN 0
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void alarmHandler(int sig);
void systemError();
char * intToString(int num , char number[4]);
static pid_t processId1, processId2;
int main(int argc, char ** argv){
pid_t pid1, pid2;
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = alarmHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGALRM, &exitSig, NULL);
if (argc < 2){
systemError();
} else {
int x = atoi(argv[1]);
alarm(x);
}
int fields[2];
if (pipe(fields)){
systemError();
}
if ((pid1 = fork()) == 0){
printf("trying to exec1\n");
close(STDIN);
dup(fields[0]);
close(fields[0]);
close(fields[1]);
if(execlp("./ex2_inp", "./ex2_inp", NULL)){
systemError();
}
} else {
processId1 = pid1;
if ((pid2 = fork()) == 0){
char number[350];
printf("trying to exec2\n");
close(STDOUT);
dup(fields[1]);
close(fields[0]);
close(fields[1]);
char * pidString = intToString(processId1, number);
if(execlp("./ex2_upd","./ex2_upd",pidString, NULL)){
systemError();
}
} else{
processId2 = pid2;
}
}
close(fields[0]);
close(fields[1]);
pause();
return 1;
}
/***********************
* handler for alarm signal
*************************/
void alarmHandler(int sig){
kill(processId2, SIGINT);
kill(processId1, SIGINT);
exit(1);
}
/***********************
* turn pid to string
*************************/
char * intToString(int num , char number[350]){
sprintf(number, "%d", num);
return number;
}
ex2_inp:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char * buffer[80];
read(1, buffer, 80);
printf("%s", buffer);
}
ex2_upd:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
thanks
ex2_upd.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
sleep(1); /* This was pause - causing ex2_inp read() to wait forever, since read() on pipe needs to either fill buffer or END_OF_FILE, unless we make the filedescriptor in the read-end non-blocking via fcntl() */
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
ex2_inp.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char buffer[80]; /* removed * */
read(0, buffer, 80); /* stdin is fd=0, not 1 */
printf("-> %s <-\n", buffer); /* added \n, forces new-line */
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
void *func(void *ptr);
int file;
int main()
{
pthread_t thread1, thread2;
int iret1, iret2;
int p;
p=1;
file=open("file1.txt", O_CREAT | O_TRUNC | O_RDWR , 0666);
iret1 = pthread_create(&thread1, NULL, func, (void *)&p);
pthread_join(thread1, NULL);
close(file);
exit(0);
}
void *func(void *ptr)
{
int *num;
int i;
num = (int *)ptr;
printf("%d ", *num);
for (i=0; i<10; i++)
{
printf("%d", *num);
write(file, *num, sizeof(*num));
}
}
How to write integer var to file using write() function in c?
This is my code. The problem is in the func(). If I use chars or const int it's working fine.
First, read the man page of write(). It writes bytes, not element types.
So, what you are trying to achieve, cannot be accomplished directly with write(). you need to use snprintf() to convert the int to char string, which you can use with write(). Please check the following code.
1. Define a char array, print the value of the int pointer to that array using snprintf().
2. Use the char array as the argument of write(). It'll work.
NOTE: It's always a best practice to add some error check to the system calls and library calls. It provides many useful information in the case they fail.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
void *func(void *ptr);
int file;
int main()
{
pthread_t thread1, thread2;
int iret1, iret2;
int p;
p=1;
file=open("file1.txt", O_CREAT | O_TRUNC | O_RDWR , 0666);
iret1 = pthread_create(&thread1, NULL, func, (void *)&p);
pthread_join(thread1, NULL);
close(file);
exit(0);
}
void *func(void *ptr)
{
int *num;
int i, ret = -1;
num = (int *)ptr;
char buf[4] = {0}; //to use with write()
printf("%d\n", *num);
for (i=0; i<10; i++)
{
printf("%d", *num);
memset(buf, 0, sizeof (buf));
snprintf(buf, sizeof *num, "%d", *num); //print to buffer
ret = write(file, buf, strlen(buf)); //write the buf to file
if (ret < 0) //check for erroneous condition
printf("ret is %d, errno %d\n", ret, errno);
}
}
write(fd, &var, sizeof(i)); is a short fix for this question.