how to write integer var to file using write() function in c - c

#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.

Related

reading and writing int from/to shared memory in c

I'm trying to make a program where a thread writes an integer into a shared memory location and then the other thread reads and prints that integer. the problem I'm facing is that the second thread keeps reading the integer as -1.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
struct args {
void* memptr;
sem_t* semptr;
};
void *p1(void *vargp)
{
void* memory = ((struct args*)vargp)->memptr;
sem_t* semaphore = ((struct args*)vargp)->semptr;
//sem_wait(semaphore);
//sleep(0.5);
for(int i=0; i<=10; i++)
{
if (!sem_wait(semaphore)) {
printf("got in if p1\n");
sprintf(memory, "%d", i);
sem_post(semaphore);
sleep(1);
}
}
if (!sem_wait(semaphore)) {
sprintf(memory, "%d", 0);
sem_post(semaphore);
sleep(1);
}
sleep(0.1);
}
void *p2(void *vargp)
{
void* memory = ((struct args*)vargp)->memptr;
sem_t* semaphore = ((struct args*)vargp)->semptr;
sleep(0.1);
while(1)
{
if (!sem_wait(semaphore)) {
printf("got in if p2\n");
if((int)memory == 0){
break;
}
printf("%d\n", (int)memory);
sem_post(semaphore);
sleep(1);
}
}
}
const int ByteSize = 4;
const char* SharedName = "memNameTest";
const char* SemaphoreName = "semNameTest";
int main()
{
int fd = shm_open(SharedName, O_RDWR, 0644);
ftruncate(fd, ByteSize);
void* memptr = mmap(0, ByteSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
sem_t* semptr = sem_open(SemaphoreName, O_CREAT, 0644, 0);
sem_post(semptr);
struct args *Share = (struct args *)malloc(sizeof(struct args));
Share->memptr = memptr;
Share->semptr = semptr;
pthread_t thread1, thread2;
printf("Before Thread\n");
pthread_create(&thread1, NULL, p1, (void*)Share);
pthread_create(&thread2, NULL, p2, (void*)Share);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("After Thread\n");
munmap(memptr, ByteSize);
close(fd);
sem_close(semptr);
unlink(SharedName);
return 0;
exit(0);
}
I have tried changing (int)memory into *((int*)memory) but that resulted in a segmentation error.
(edit)
as suggested I tried this in a single-threaded program and got it to work as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
/* the size (in bytes) of shared memory object */
const int SIZE = 4;
/* name of the shared memory object */
const char* SharedName = "memoryInt";
/* create the shared memory object */
int shm_fd = shm_open(SharedName, O_CREAT | O_RDWR, 0644);
/* configure the size of the shared memory object */
ftruncate(shm_fd, SIZE);
/* memory map the shared memory object */
void* memptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
for(int i=1; i<=10; i++){
/* write to the shared memory object */
//sprintf(memptr, "%d", i);
memcpy(memptr, &i, sizeof(int));
printf("%d\n", *((int*)memptr));
sleep(1);
}
return 0;
}
though this still doesn't work in a multi-threaded program as i get a segmentation fault.
this is the output:
Before Thread
got in if p1
Segmentation fault
First, you have to show what happen on your terminal when you compile your program.
Secondly, the function sprintf has the declaration:
sprintf(char *str, const char *format, ...);
That means the p1 will write the null terminated string of character. In your code, i dont understand why you use the void pointer memory instead of using char pointer as the description. You should verify the read/write function by using single-threaded before applying to the multi-thread.

using threads for the first time

//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;
}

Updating shared memory by different process

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

string argument in thread function

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])
^

How to write a number (int, double) to file using file descriptor in C?

I tried this:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int out_fd = open("file.txt", O_WRONLY | O_CREAT, 0666);
int i;
scanf("%d", &i);
char tmp[12]={0x0};
sprintf(tmp,"%11d", i);
write(out_fd, tmp, sizeof(tmp));
close(out_fd);
return 0;
}
but it writes some trash to my file:
is there any good way to write a number (float, int, double) to file using file descriptor and write? Thanks
thanks guys, solved:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int out_fd = open("plik.txt", O_WRONLY | O_CREAT, 0666);
int i;
scanf("%d", &i);
char tmp[1]={0x0};
sprintf(tmp,"%d", i);
write(out_fd, tmp, strlen(tmp));
close(out_fd);
return 0;
}
You need to replace sizeof() with strlen() to get the actual length of the string to write. e.g:
write(out_fd, tmp,strlen(tmp));

Resources