How to use epoll instead of select in this code? - unix

In UNIX Network Programming Volume 1:Figure 6-22 ,there is a piece of code as follows:
/* include fig01 */
#include "unp.h"
int main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
/* end fig01 */
/* include fig02 */
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF
printf("new client: %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
ntohs(cliaddr.sin_port));
#endif
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
/*4connection closed by client */
Close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else
Writen(sockfd, buf, n);
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
/* end fig02 */
I want to know how to use "epoll" instead "select" in here,But I have little knowledge about epoll,so can anyone give me some points ? Thanks.

You can go through this link. However, Before using epoll you need to be sure of the below points -
Do you want your system to be targeted as cross platform system (I mean which can be run under multiple operating system?) - Because epoll is available only in Linux system.
What is your targeted kernel version of Linux? Because epoll is only available in Linux 2.6. In case both these questions are answered and you feel epoll is not a restriction, you can go ahead with this.
HTH!

Related

Nginx Master process create a thread, but I can't kill it by pthread_cancel or pthread_kill,

In nginx master process, start a thread to implement a timer.
Fake code:
void* timer_proc(void* pdata)
{
struct timeval tv = {0};
timer_handle* phandle = (timer_handle*)pdata;
prctl(PR_SET_NAME, phandle->desc);
/* 设置线程取消点 */
//pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); /* 线程可取消 */
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); /* 实时取消, PTHREAD_CANCEL_DEFERRED 延时取消 */
while(phandle->repeat && !(phandle->stop))
{
tv.tv_sec = phandle->timeout;
tv.tv_usec = 0;
int nret = select(0,NULL,NULL,NULL,&tv);
if (0 == nret) {
phandle->pfunc(phandle->pdata);
}
}
return NULL;
}
But I can't kill it by pthread_cancel()or pthread_kill(), return error 3, errno 11, strerr: 'Resource temporarily unavailable'.

Downloading Image to a specific folder using gp_filesystem_get_file()

Trying my hands on libgphoto2 library examples and while going through simple-capture.c file. Can i download foo.jpg captured image to a specified folder on my computer?
As far as i understood, in capture_to_file() camera_file_path.folder is the folder in which the file can be found on the camera. So open() should specify the host(computer) location. But nothing worked, i get following error:
You need to specify a folder starting with /store_xxxxxxxxx/
Am i missing something here? Any help would be appreciated, thanks!
I got this working.
Written small application for multiple cameras. Including main() for about question.
int main(int argc, char **argv)
{
CameraList *list;
Camera **cams;
int retval, count, i;
GPContext *context;
FILE *f;
char *data;
unsigned long size;
const char *name, *value;
/*
* Create context
*/
context = sample_create_context();
/*
* Setup Images DB directory.
*/
char* home = getenv("HOME");
if (home == NULL)
{
printf("Error: Unable to fetch home env! \n");
exit(1);
}
char* path = "/Desktop/mw/";
size_t len = strlen(home) + strlen(path) + 1;
char* imgdb = malloc(len);
if (imgdb == NULL)
{
printf("Error: Unable to malloc(). \n");
exit(1);
}
strcpy(imgdb, home);
strcat(imgdb, path);
directory_exists_or_create(imgdb);
/*
* Logs
*/
gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
/*
* Detect all the cameras that can be autodetected
*/
retval = gp_list_new(&list);
if (retval < GP_OK)
{
printf("Unable to create camera list.\n");
return 1;
}
count = sample_autodetect(list, context);
if (count < GP_OK)
{
printf("No cameras detected.\n");
return 1;
}
/*
* Now open all the cameras we autodetected for usage.
*/
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof(Camera*), count);
for (i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
retval = sample_open_camera(&cams[i], name, value, context);
if (retval < GP_OK)
{
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
if (argc > 0)
{
while ((++argv)[0])
{
if (argv[0][0] == '-')
{
switch (argv[0][1])
{
case 'h':
case 'H':
{
/* Now call a simple function in each of those cameras. */
for (i = 0; i < count; i++)
{
CameraText text;
char *owner;
retval = gp_camera_get_summary (cams[i], &text, context);
if (retval < GP_OK)
{
fprintf (stderr, "Failed to get summary.\n");
continue;
}
gp_list_get_name (list, i, &name);
gp_list_get_value (list, i, &value);
printf("%-30s %-16s\n", name, value);
printf("Summary:\n%s\n", text.text);
/* Query a simple string configuration variable. */
retval = get_config_value_string (cams[i], "owner", &owner, context);
if (retval >= GP_OK)
{
printf("Owner: %s\n", owner);
free (owner);
}
else
{
printf("Owner: No owner found.\n");
}
}
}
/* Graceful exit from the program */
goto exit_;;
default:
printf("Unknown option -%c\n\n", argv[0][1]);
break;
}
}
}
}
/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
* init function seems to traverse the entire filesystem on the camera. This
* is partly why it takes so long.
* (Marcus: the ptp2 driver does this by default currently.)
*/
printf("Cameras init. Takes about 10 seconds each.\n");
for (i = 0; i < count; i++)
{
retval = gp_camera_init(cams[i], context);
if (retval != GP_OK)
{
printf(" Camera [%d] init failed with retval %d\n", i, retval);
exit (1);
}
}
printf(" ----------------\n");
printf(" Sampler is ready \n");
printf(" ----------------\n");
printf("Usage : \n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
char get_key;
char exit_key = 0;
char bcr_buf[128] = {0};
int hemispheres_counts = 0;
int rotar_steps = 0;
do
{
get_key = getchar();
switch (get_key)
{
// Gracefull Exit
case _ESC_:
exit_key = 1;
break;
// Manual insert mode
case 'i':
case 'I':
printf("ACTION: Type in the name.\n");
scanf("%128s", bcr_buf);
process:
press_enter();
printf("ACTION: Shall we start? press return key.\n");
press_enter();
hemispheres_counts = 0;
rotar_steps = 0;
char product_filename[256] = {0};
strcpy(product_filename, imgdb);
strcat(product_filename, bcr_buf);
if (directory_exists_or_create(product_filename))
{
printf("\n\n!!! ATTENTION: The product already exists !!!\n\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
while (hemispheres_counts < MAX_HEMISPHERES)
{
while (rotar_steps < MAX_ROTAR_STEPS)
{
for (i = 0; i < count; i++)
{
capture_to_memory(cams[i], context, (const char**)&data, &size);
char fname[64] = {0};
char mk_filename[256] = {0};
strcpy(mk_filename, product_filename);
snprintf(fname, sizeof(fname), "/%d-%d-%d.jpg", i, hemispheres_counts, rotar_steps);
strcat(mk_filename, fname);
printf("file name %s\n", mk_filename);
f = fopen(mk_filename, "wb");
if (f)
{
retval = fwrite (data, size, 1, f);
if (retval != size)
{
printf(" fwrite size %ld, written %d\n", size, retval);
}
fclose(f);
}
else
{
printf(" fopen *.jpg failed. %s\n", strerror(errno));
}
usleep(500*1000);
}
rotar_steps++;
}
rotar_steps = 0;
hemispheres_counts++;
if (hemispheres_counts < MAX_HEMISPHERES)
{
printf("Flip the product and hit 'RETURN' key\n");
press_enter(); // This expect some input from user, thats it.
printf("Started capturing other hemisphere!\n");
} else {
printf("Sampling Done for barcode: %s\n", bcr_buf);
printf(" -------------------------------------\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
}
break;
}
} while (exit_key != 1);
exit_:
/*
* Release all the resources.
*/
printf("\nReleasing all the resources ... \n");
for (i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
}
if (cams) {
free(cams);
}
free(imgdb);
#if defined(BARCODE_ENABLED)
close_bcr();
#endif
printf("Done.\n");
return 0;
}

select() message queue failed as bad address(EFAULT) on AIX 6.1.0.0

On AIX 6.1.0.0, select() system call support for message queue, see http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/select.htm?lang=en
But the below code return failed with errno 14(EFAULT) after select() called:
int msgid = msgget(MQ_KEY, IPC_CREAT|06666);
if (-1 == msgid) {
if (errno != EEXIST) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
msgid = msgget(MQ_KEY, 0);
if (-1 == msgid) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
}
DTRACE("msgget() success: msgid[%d]", msgid);
/* time out */
struct timeval to;
to.tv_sec = 10;
to.tv_usec = 0;
/* select list */
struct {
int msgids[1];
} rlist, wlist, elist;
rlist.msgids[0] = msgid;
wlist.msgids[0] = msgid;
elist.msgids[0] = msgid;
/* number of list */
int nlist = 1 << 16;
/* int ret = select(nlist, (struct fd_set*)&rlist, (struct fd_set*)&wlist, (struct fd_set*)&elist, &to); */
int ret = select(nlist, (struct fd_set*)&rlist, NULL, NULL, &to);
if (0 == ret) {
WTRACE("select() timeout: ret[%d]", ret);
}
else if (ret < 0) {
ETRACE("select() failed: ret[%d], errno[%d]", ret, errno);
}
else {
ITRACE("select() success");
}
return 0;
Message queue support in select() and poll() is an AIX extension that is no longer enabled by default when compiling on AIX 5.3 and later versions. To enable it, compile with -D_MSGQSUPPORT (or #define _MSGQSUPPORT 1 before the first #include).
It is not mentioned on the select() manual page but the option is mentioned on the poll() manual page, and the same flag enables message queue support for both functions.

How do I loop mount programmatically?

I have recently written a guide on how to mount partitions from image files on Raspberry Pi.SE. The instructions are rather complicated and I have a bit of time, so want to replace them by a C program. I have successfully listed the partitions of the image and calculated to appropriate offsets.
In the original instructions, we needed to run
$ sudo mount -o loop,offset=80740352 debian6-19-04-2012.img /mnt
I now need to do this in code. I have found the mount function and libmount in util-linux.
I have now found loopdev.c in util-linux. Is there an easy way to create loop devices or do I have to learn from this code and use ioctl?
The following function binds the loop device device to file at offset. It returns 0 on success, 1 otherwise.
int loopdev_setup_device(const char * file, uint64_t offset, const char * device) {
int file_fd = open(file, O_RDWR);
int device_fd = -1;
struct loop_info64 info;
if(file_fd < 0) {
fprintf(stderr, "Failed to open backing file (%s).\n", file);
goto error;
}
if((device_fd = open(device, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open device (%s).\n", device);
goto error;
}
if(ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) {
fprintf(stderr, "Failed to set fd.\n");
goto error;
}
close(file_fd);
file_fd = -1;
memset(&info, 0, sizeof(struct loop_info64)); /* Is this necessary? */
info.lo_offset = offset;
/* info.lo_sizelimit = 0 => max avilable */
/* info.lo_encrypt_type = 0 => none */
if(ioctl(device_fd, LOOP_SET_STATUS64, &info)) {
fprintf(stderr, "Failed to set info.\n");
goto error;
}
close(device_fd);
device_fd = -1;
return 0;
error:
if(file_fd >= 0) {
close(file_fd);
}
if(device_fd >= 0) {
ioctl(device_fd, LOOP_CLR_FD, 0);
close(device_fd);
}
return 1;
}
References
linux/loop.h
piimg

Http Streaming from ffmpeg, How to get a sequenced packet?

I am trying to make http streaming program.
So I follow this code at this.
However, when i decode, only one frame is decoded.
I think I need call back function.
Do you know how to make a call back function?
I know 'asf' packet's call back function is like int read_data(void *opaque, char *buf, int buf_size)
But the other formats(mp3, ogg, aac, ..) doesn't work..
Please help me.
Any advice or comment are very appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
int main(int argc, char **argv)
{
static AVInputFormat *file_iformat;
static AVFormatContext *pFormatCtx;
AVFormatParameters params;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
const char url[] = "http://listen.radionomy.com/feelingfloyd";
avcodec_register_all();
avdevice_register_all();
av_register_all();
av_log_set_level(AV_LOG_VERBOSE);
file_iformat = av_find_input_format("mp3"); /* mp3 demuxer */
if (!file_iformat)
{
fprintf(stderr, "Unknown input format: %s\n", &url[0]);
exit(1);
}
//file_iformat->flags |= AVFMT_NOFILE; /* ??? */
params.prealloced_context = 0;
if (av_open_input_file(&pFormatCtx, &url[0], file_iformat, 0, &params) != 0)
{
fprintf(stderr, "err 1\n");
exit(2);
}
/* poulates AVFormatContex structure */
if (av_find_stream_info(pFormatCtx) < 0)
{
fprintf(stderr, "err 2\n");
}
/* sanity check (1 stream) */
if (pFormatCtx->nb_streams != 1 &&
pFormatCtx->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
{
fprintf(stderr, "err 3\n");
}
pCodecCtx = pFormatCtx->streams[0]->codec;
/* find decoder for input audio stream */
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
fprintf(stderr, "err 4: unsupported codec\n");
}
if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
if (avcodec_open(pCodecCtx, pCodec) < 0)
{
fprintf(stderr, "err 5\n");
}
{
uint8_t *pAudioBuffer;
AVPacket pkt;
int ret;
int data_size = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
av_init_packet(&pkt);
//pkt.data=NULL;
//pkt.size=0;
//pkt.stream_index = 0;
pAudioBuffer = av_malloc(data_size * sizeof(int16_t));
while (av_read_frame(pFormatCtx, &pkt) == 0) {
//data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
ret = avcodec_decode_audio3(pFormatCtx->streams[pkt.stream_index]->codec,
(int16_t *)pAudioBuffer, &data_size, &pkt);
/* got an error (-32) here */
if (ret < 0) {
av_strerror(ret, (char *)pAudioBuffer, data_size);
fprintf(stderr, "err 6 (%s)\n", pAudioBuffer);
break;
}
printf("size=%d, stream_index=%d |ret=%d data_size=%d\n",
pkt.size, pkt.stream_index, ret, data_size);
av_free_packet(&pkt);
}
av_free(pAudioBuffer);
}
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
return 0;
}
I figure out this problem by using av_open_input_file.
I got a this problem when I made a iphone app that play http audio streaming. And the above code didn't work. only played just some of audio frame. it also means there are so many buffering.
However After using iphone audio callback function and large audio buffer, it works fine.
Those who are curious about the final code send me a messege.

Resources