shared memory father and child in c - memory

David Shwartz helped me alot and now it kinda works...
do you have any idea for more elgant way to parse the input, if the input consists more than 2 numbers to add which need to be processed by the child ? I want the child to get only two integers so that's why I created the shared memory so the father will send the child the result(shared memory) + another integer.
Thank you all.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
volatile int *shared=0;
int shmid;
int main()
{
char line[256];
int readByte;
int fd[2]; //pipe to son, who processes addition
int pid;
shmid=shmget ( IPC_PRIVATE, sizeof(int) , 0600 );
shared=shmat ( shmid, 0 , 0);
if ( pipe(fd) )
{
perror("pipe");
exit(-1);
}
pid=fork();
if (pid!=0) // father
{
close (fd[0]);
readByte=read(0, line, 256);
line[readByte-1]='\0';
printf("%d",readByte);
int arr[2];
int i=0;
int j=0;
int flag=0;
char num[10];
while (i<readByte)
{
if (line[i]=='+' )
{
i++;
j=0;
flag=1;
}
while (line[i]!='+' && line[i]!='\0')
{
num[j]=line[i];
i++;
j++;
}
num[j]='\0';
if (flag==0)
arr[0]=atoi(num);
else
{
arr[1]=atoi(num);
i++;
}
}
printf("first %d\n",arr[0]);
printf("sec %d\n",arr[1]);
write(fd[1], &arr, sizeof(arr));
wait(NULL);
printf ( "%d\n" , *shared );
}
else
// son
{
int arr[2];
int sum;
readByte = read(fd[0], &arr, sizeof(arr));
printf("son printing: %d\n",arr[0]);
printf("son printing: %d\n",arr[1]);
sum =arr[0]+arr[1];
*shared=sum;
close (fd[0]);
shmdt ( (const void *) shared );
}
shmdt ( (const void *) shared );
shmctl ( shmid , IPC_RMID , 0 );
close(fd[1]);
return 0;
}

You throw away the return value of shmat. And you expect shared to be shared, but it's just a regular variable. Also, you need to prevent the compiler from optimizing away accesses to the shared memory. Here it is with all the fatal bugs fixed:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
volatile int *shared;
int shmid;
int main()
{
int s,i;
shmid=shmget ( IPC_PRIVATE, sizeof(int), 0600 );
shared=shmat ( shmid, 0 , 0);
*shared=100;
printf ( "%d\n" , *shared);
if ( fork()==0 ) // son
{
*shared=1000;
shmdt ( (const void *) shared );
}
else // father
{
wait ( &s );
printf ( "%d\n" , *shared);
shmdt ( (const void *) shared );
shmctl ( shmid , IPC_RMID , 0 );
}
return 0;
}

Related

hugepages allocated by mmap is slower than posix_memalign

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <sys/mman.h>
#include <time.h>
#define HUGEPAGE 2048*1024
void *normal_malloc(int len)
{
void *ptr = malloc(len);
bzero(ptr, len);
return ptr;
}
void *trans_malloc(int len)
{
void *ptr = NULL;
int ret = posix_memalign(&ptr, HUGEPAGE, len);
if(ret) perror("posix_memalign");
ret = madvise(ptr, len, MADV_HUGEPAGE);
bzero(ptr, len);
return ptr;
}
void *mmap_malloc(int len)
{
void *ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1,0);
return ptr;
}
int main(int argc, char **argv)
{
char *ptr = NULL;
int len = HUGEPAGE*256;
srand(time(NULL));
switch(argc){
case 1: ptr = normal_malloc(len);break;
case 2: ptr = trans_malloc(len);break;
case 3: ptr = mmap_malloc(len); break;
}
long j = 0;
for(int i=0;i<len;i++){
j += ptr[rand()%len];
}
return 0;
}
I use normal malloc and posix_memalign and mmap to test performance.
My test result is :
malloc cost about 29.7s, posix_memalign cost about 23.5s, and mmap is very near with malloc.
Both posix_memalign and mmap uses hugepages. Why one has obvious improvement, the other not? Do I use mmap in the wrong way?
I don't do bzero for mmap since the man pages says "its contents are initialized to zero".

How may I use PCAP or other library to parse layer 3 frame received from TUN?

This is how I receive layer 3 frame from TUN.
Written based on docs:
https://www.kernel.org/doc/Documentation/networking/tuntap.txt
http://backreference.org/2010/03/26/tuntap-interface-tutorial/
Unpacking from http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <stdarg.h>
/* buffer for reading from tun/tap interface, must be >= 1500 */
#define BUFSIZE 2000
int tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;
if (!dev) {
return -1;
}
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
* IFF_MULTI_QUEUE - Create a queue of multiqueue device
*/
ifr.ifr_flags = IFF_TUN;
strcpy(ifr.ifr_name, dev);
if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
return fd;
err = ioctl(fd, TUNSETIFF, (void *)&ifr);
if (err) {
close(fd);
goto err;
}
strcpy(dev, ifr.ifr_name);
return fd;
err:
close(fd);
return err;
}
int main() {
char *tun_name;
tun_name = malloc(IFNAMSIZ);
tun_name[0] = '\0';
int tun_fd = tun_alloc(tun_name);
if (tun_fd < 0) {
puts("Try as root");
exit(1);
}
if (ioctl(tun_fd, TUNSETPERSIST, 0) < 0) {
perror("disabling TUNSETPERSIST");
exit(1);
}
printf("Set interface '%s' nonpersistent\n", tun_name);
struct layer3_frame
{
uint16_t flags;
uint16_t proto;
uint8_t version;
unsigned char payload[];
} __attribute__((packed));
int nread;
char buffer[BUFSIZE];
while(1) {
nread = read(tun_fd, buffer, sizeof(buffer));
if(nread < 0) {
perror("Reading from interface");
close(tun_fd);
exit(1);
}
/* Do whatever with the data */
printf("Read %d bytes from device %s\n", nread, tun_name);
struct layer3_frame* l3f = (struct layer3_frame*)(buffer);
printf("FLAGS %d, PROTO %d, VER %d", l3f->flags, l3f->proto, l3f->version);
// E.g. FLAGS 0, PROTO 56710, VER 96
// Why PROTO is not 4 or 6, why VER is not 4 or 6?
// MAIN: HOW TO USE PCAP TO PARSE l3f FURTHER
// AND GET INFO UP TO SNI (server name indication), e.g.
}
return 0;
}
To play:
gcc index.c
sudo ./a.out
sudo ip link set tun0 up
PCAP usually is not used for parsing packets.
You may use however:
#include <netinet/ip.h>
#include <netinet/ip6.h>
//...
struct layer3_frame
{
uint16_t flags; // FLAGS from TUN
uint16_t proto; // PRPTO from TUN
unsigned char payload[]; // FRAME/PACKET
} __attribute__((packed));
const struct ip* ippacket = (struct ip*)(l3p->payload);
printf("Version is %d", ippacket->ip_v)
3. About strange values for PROTO like 56710 try printf("FFF: %x", ntohs(56710)) you will get 86dd which you may look up at https://en.wikipedia.org/wiki/EtherType

How to Create threads recursively without Loops

I would like to create a code that will:
create recursive threads without using loops, the threads has to execute certain routine. I am using Pthread_create on ubuntu
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 8
void *PrintHello(void *threadid)
{
printf("\n%d: Hello World!\n", threadid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc, t;
for(t=0; t<NUM_THREADS; t++)
{
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
Yes you can create thread without using for loop , I have modified your code and used function recursion to create pthread..
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 8
pthread_t threads[NUM_THREADS];
void *PrintHello(void *threadid)
{
printf("\n%d: Hello World!\n", threadid);
pthread_exit(NULL);
}
void create_thread(int n){
if (n > 0 ){
//Create thread
printf("Creating thread %d\n", ((NUM_THREADS - n) + 1) );
//NUM_THREADS - n to start index from 0
int rc = pthread_create(&threads[NUM_THREADS - n], NULL, PrintHello, (void *)(NUM_THREADS - n));
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
n--;
create_thread(n);
}
return;
}
int main(int argc, char *argv[])
{
int rc, t;
create_thread( NUM_THREADS );
//Wait to finish all thread
for (t = 0; t < NUM_THREADS; t++)
{
pthread_join(threads[t],NULL);
}
pthread_exit(NULL);
return 0;
}
Hope this will help you.

capture’ was not declared in this scope capture = cvCaptureFromCAM( 0 ); how to fix it

I was following a tutorial on web for an OpenCV library to detect eyes
when i compile it this error appears I tried to fix it but didn't find a
solution.
main.cpp:59:1: error: ‘capture’ was not declared in this scope
capture = cvCaptureFromCAM( 0 );
The code is long I put only the part that I think causing this error .
: Full code
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <queue>
#include <stdio.h>
#include <math.h>
#include "constants.h"
#include "findEyeCenter.h"
#include "findEyeCorner.h"
/** Function Headers */
void detectAndDisplay( cv::Mat frame );
int main( )
{
cv::Mat frame;
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };
createCornerKernels();
ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);
capture = cvCaptureFromCAM( 0 );
if( capture)
{
while( true )
{
frame = cvQueryFrame( capture );
// mirror it
imshow("Video",frame);
cv::flip(frame, frame, 1);
frame.copyTo(debugImage);
// Apply the classifier to the frame
if( !frame.empty() ) {
detectAndDisplay( frame );
}
else {
printf(" --(!) No captured frame -- Break!");
break;
}
imshow(main_window_name,debugImage);
int c = cv::waitKey(10);
if( (char)c == 'c' ) { break; }
if( (char)c == 'f' ) {
imwrite("frame.png",frame);
}
}
}
releaseCornerKernels();
return 0;
}
}
try to use VideoCapture capture(0);

HIDAPI in two threads

According to https://github.com/signal11/hidapi/issues/72 HIDAPI ought to be thread safe on Linux machines. However, I can't get it working at all. This is what I do:
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include "hidapi.h"
hid_device *handle;
static void *TaskCode(void *argument)
{
int res;
//hid_device *handle;
unsigned char buf[64];
// res = hid_init();
// if( res == -1 )
// {
// return (void*)1;
// }
//
// handle = hid_open(0x0911, 0x251c, NULL);
// if( handle == NULL )
// {
// return (void*)2;
// }
printf( "while 2\n");
while( 1 )
{
memset( buf, 64, 0 );
res = hid_read(handle, buf, 0);
if( res == -1 )
{
return (void*)3;
}
printf( "received %d bytes\n", res);
for (int i = 0; i < res; i++)
printf("Byte %d: %02x ", i+1, buf[i]);
//printf( "%02x ", buf[0]);
fflush(stdout);
}
return (void*)0;
}
int main(int argc, char* argv[])
{
int res;
//hid_device *handle;
unsigned char buf[65];
res = hid_init();
if( res == -1 )
{
return 1;
}
handle = hid_open(0x0911, 0x251c, NULL);
if( handle == NULL )
{
return 2;
}
hid_set_nonblocking( handle, 0 );
pthread_t thread;
int rc = pthread_create(&thread, NULL, TaskCode, NULL);
printf( "while 1\n");
while(1)
{
int a = getchar();
if( a == 'a')
{
// Get Device Type (cmd 0x82). The first byte is the report number (0x0).
buf[0] = 0x0;
buf[1] = 0x82;
res = hid_write(handle, buf, 65);
if( res != -1 )
printf( "write ok, transferred %d bytes\n", res );
else
{
printf( "write error\n" );
char* str = hid_error(handle);
printf( "error: %s\n", str );
return 1;
}
}
else if( a== 'b')
break;
}
void* trc;
rc = pthread_join(thread, &trc);
printf( "rc code: %d\n", (int)trc );
// Finalize the hidapi library
res = hid_exit();
return 0;
}
If I don't use the global handle, I get 'write error' every time. If I do, as in the example, formally everything works but hid_read always returns 0 bytes... Of course, if I do simple hid_write() followed by hid_read(), I'll get the correct reply to the command 0x82 as intended. I'm really lost here, am I overlooking something?
EDIT: to clarify, zero bytes return also for everything, incl. buttons on mouse etc. So it seems to work but the data buffer is always zero bytes.
Shame on me, a dumb mistake. The code should be:
memset( buf, 0, 64 );
res = hid_read(handle, buf, 64);
and then it works. Should sleep more and write less!

Resources