I'm using Fedora 19 with the kernel of 3.11.6-200.fc19.x86_64
I had some errors when learning proc_fs.h
It seems that these codes can be normally compiled on Ubuntu 12.04, I just cannot figure out what's wrong with it on Fedora.
[root#frederick-pc Test]# make
make -C /lib/modules/3.11.6-200.fc19.x86_64/build M=/home/frederick/Documents/HW_2nd/Test modules
make[1]: Entering directory `/usr/src/kernels/3.11.6-200.fc19.x86_64'
CC [M] /home/frederick/Documents/HW_2nd/Test/rw_proc.o
/home/frederick/Documents/HW_2nd/Test/rw_proc.c: In function ‘rw_proc_init’:
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:43:2: error: implicit declaration of function ‘proc_create_entry’ [-Werror=implicit-function-declaration]
p = proc_create_entry(PROCFS_NAME, 0644, NULL);
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:43:4: warning: assignment makes pointer from integer without a cast [enabled by default]
p = proc_create_entry(PROCFS_NAME, 0644, NULL);
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:51:3: error: dereferencing pointer to incomplete type
p->read_proc = procfile_read;
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:52:3: error: dereferencing pointer to incomplete type
p->write_proc = procfile_write;
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:54:3: error: dereferencing pointer to incomplete type
p->mode = S_IFREG | S_IRUGO;
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:55:3: error: dereferencing pointer to incomplete type
p->uid = 0;
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:56:3: error: dereferencing pointer to incomplete type
p->gid = 0;
^
/home/frederick/Documents/HW_2nd/Test/rw_proc.c:57:3: error: dereferencing pointer to incomplete type
p->size = 37;
^
cc1: some warnings being treated as errors
make[2]: *** [/home/frederick/Documents/HW_2nd/Test/rw_proc.o] Error 1
make[1]: *** [_module_/home/frederick/Documents/HW_2nd/Test] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.11.6-200.fc19.x86_64'
make: *** [default] Error 2
here're my codes
rw_proc.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/proc_fs.h>
#include<asm/uaccess.h>
#define PROCFS_MAX_SIZE 1024
#define PROCFS_NAME "my_procfile_1k"
MODULE_LICENSE("GPL");
static struct proc_dir_entry *p = NULL;
static char procfs_buffer[PROCFS_MAX_SIZE];
static unsigned long procfs_buffer_size = 0;
static int procfile_read(char *buffer,char **buffer_location,off_t offset, int buffer_length, int *eof,void *data)
{
int ret;
printk(KERN_INFO "procfile_read (/proc/%s) called\n", PROCFS_NAME);
if (offset > 0)
{
ret = 0;
}
else
{
memcpy(buffer, procfs_buffer, procfs_buffer_size);
ret = procfs_buffer_size;
}
return ret;
}
static int procfile_write(struct file *file, const char *buffer, unsigned long count,void *data)
{
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return EFAULT;
}
return procfs_buffer_size;
}
static int rw_proc_init(void)
{
p = proc_create_entry(PROCFS_NAME, 0644, NULL);
if (p == NULL)
{
remove_proc_entry(PROCFS_NAME, NULL);
printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
PROCFS_NAME);
return ENOMEM;
}
p->read_proc = procfile_read;
p->write_proc = procfile_write;
//p->owner = THIS_MODULE;
p->mode = S_IFREG | S_IRUGO;
p->uid = 0;
p->gid = 0;
p->size = 37;
printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME);
return 0;
}
static void rw_proc_exit(void)
{
remove_proc_entry(PROCFS_NAME, NULL);
printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME);
}
module_init(rw_proc_init);
module_exit(rw_proc_exit);
Who can help me? THX
Well finally i resolved the problem myself
it seems that since the version of 3.10.0, the function of proc_create_entry() has been deleted and replaced by proc_create()
so just replace them in the codes if you're compiling with a kernel newer than 3.10.0
Your variable p is not declared, this is what the compiler is trying to tell you. You'd just have to declare the variable locally at the beginning of the function like that:
struct proc_dir_entry *p = proc_create_entry(PROCFS_NAME, 0644, NULL);
(if struct proc_dir_entry* is really the type that the function returns, I didn't check.)
Related
I need a bit of help with my round robin scheduler. It is meant to take external C files and place them in a queue while displaying their current state, and execute them through round robin scheduling. Here is what I have so far:
#include<pthread.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
enum states {running, ready, waiting, idle};
struct process{
//command to run process
enum states state;
int id;
};
struct process procs[5];
int procSize = 5;
void *runProcess(struct process *p)
{
while(1)
{
printf("Process %i is running", p->id);
sleep(1);
}
}
void *takeInput(void *vargp)
{
//print process statuses when 'procs' is entered
while(1)
{
char *str[64];
fgets(str, 64, stdin);
if (strcmp(str, "procs"))
{
for (int i = 0; i < procSize; i++)
{
printf("Process %i: %i\n", procs[i].id, procs[i].state);
}
}
}
}
void *schedule(void *vargp)
{
struct process p = procs[0];
if (p.state == idle)
{
p.state = ready;
}
if (p.state == ready)
{
p.state = running;
pthread_t run;
pthread_create(&run, NULL, runProcess, &p);
//pthread_join(run, NULL);
sleep(5);
pthread_cancel(run);
p.state = ready;
for(int i = procSize - 1; i > 0; i--)
{
procs[i-1] = procs[i];
}
procs[procSize] = p;
}
else if (p.state == waiting)
{
for(int i = procSize - 1; i > 0; i--)
{
procs[i-1] = procs[i];
}
procs[procSize] = p;
}
}
int main()
{
for (int i = 0; i < 5; i++)
{
struct process p;
p.state = idle;
p.id = i;
procs[i] = p;
}
pthread_t schedulerid;
pthread_t inputid;
pthread_create(&schedulerid, NULL, schedule, NULL);
//pthread_join(schedulerid, NULL);
pthread_create(&inputid, NULL, takeInput, NULL);
//pthread_join(inputid, NULL);
}
When I attempt to run this, I get no errors, only warnings, and nothing happens. What do I need to improve on? Is there an issue with trying to call functions using threads? Any help is appreciated.
UPDATED WITH WARNINGS:
Sched.c:35:20: warning: passing argument 1 of ‘strcmp’ from incompatible pointer type [-Wincompatible-pointer-types]
35 | if (strcmp(str, "procs"))
| ^~~
| |
| char **
In file included from Sched.c:3:
/usr/include/string.h:137:32: note: expected ‘const char *’ but argument is of type ‘char **’
137 | extern int strcmp (const char *__s1, const char *__s2)
| ~~~~~~~~~~~~^~~~
Sched.c: In function ‘schedule’:
Sched.c:56:36: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types]
56 | pthread_create(&run, NULL, runProcess, &p);
| ^~~~~~~~~~
| |
| void * (*)(struct process *)
In file included from Sched.c:1:
/usr/include/pthread.h:200:15: note: expected ‘void * (*)(void *)’ but argument is of type ‘void * (*)(struct process *)’
200 | void *(*__start_routine) (void *),
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Lets fix those warnings
char *str[64];
fgets(str, 64, stdin);
if (strcmp(str, "procs"))
should be
char str[64];
fgets(str, 64, stdin);
if (strcmp(str, "procs"))
then
pthread_create(&run, NULL, runProcess, &p);
The function must be a void* func (void*)
So change run process to
void *runProcess(void *v)
{
struct process *p =(struct process*)v;
while(1)
{
printf("Process %i is running", p->id);
sleep(1);
}
}
ie pass a void * and cast it to what you need
this compiles with no warning now.
Finally put your joins back in
int pt1 = pthread_create(&schedulerid, NULL, schedule, NULL);
int pt2 = pthread_create(&inputid, NULL, takeInput, NULL);
printf("%d %d \n", pt1, pt2);
pthread_join(schedulerid, NULL);
pthread_join(inputid, NULL);
as a final note - you really must test the returns from all your system calls to make sure they worked
here it is running
pm100#paul-think:~/ut$ gcc ggg.c -g -lpthread
pm100#paul-think:~/ut$ ./a.out
Process 0 is running
My Speller program is working perfectly fine except for a memory leak that I can't seem to wrap my head around. I have already satisfied every other check50 requirement and I would very much appreciate someone's help regarding my code logic. Thank you in advanced to whoever would dedicate some of their time to helping me! Anyways, here is the code:
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 1000;
// Hash table
node *table[N];
// File pointer
FILE *read;
// Node pointer
node *new_node;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
// Input word into hash function
int word_index = hash(word);
// Check if word is in dictionary
for (node *tmp = table[word_index]; tmp != NULL; tmp = tmp->next)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
}
return false;
}
// Hashes word to a number
// Credits to Neel Mehta from http://stackoverflow.com/questions/2571683/djb2-hash-function
unsigned int hash(const char *word)
{
unsigned long index = 5381;
for (const char *ptr = word; *ptr != '\0'; ptr++)
{
index = ((index << 5) + index) + tolower(*ptr);
}
return index % N;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
// Initialize word
char dict_word[LENGTH + 1];
// Open file for reading
read = fopen(dictionary, "r");
if (read == NULL)
{
// Terminate program
printf("Cannot open dictionary\n");
return false;
}
// Loop until end of file
while (fscanf(read, "%s", dict_word) != EOF)
{
// Initialize node pointer
new_node = malloc(sizeof(node));
if (new_node == NULL)
{
// Terminate program
free(new_node);
printf("Insufficient memory storage\n");
return false;
}
// Copy word into node pointer
strcpy(new_node->word, dict_word);
// Set pointer to null
new_node->next = NULL;
// Call upon hash function
int word_index = hash(new_node->word);
// Index result into hash table
if (table[word_index] == NULL)
{
// Open node
table[word_index] = new_node;
}
else
{
// !Open node
new_node->next = table[word_index];
table[word_index] = new_node;
}
}
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// Iterate through the whole hash table
int word_counter = 0;
for (int i = 0; i < N; i++)
{
if (table[i] == NULL)
{
// Skip iteration
}
else
{
// Check how many words
for (node *tmp = table[i]; tmp != NULL; tmp = tmp->next)
{
word_counter++;
}
}
}
return word_counter;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// Iterate through the hash function
for (int i = 0; i < N; i++)
{
if (table[i] == NULL)
{
// Skip iteration
}
else
{
// Initialize pointers
node *tmp_first = table[i];
node *tmp_second = table[i]->next;
// Iterate through the linked list
while (tmp_second != NULL)
{
free(tmp_first);
tmp_first = tmp_second;
tmp_second = tmp_second->next;
}
}
}
free(new_node);
fclose(read);
return true;
}
Valgrind says that 56 bytes in 1 block is still reachable, specifically referring to:
new_node = malloc(sizeof(node));
which is located in the load function. What I'm confused about is that I freed it at the end:
free(new_node);
yet it seems that it has no effect. This is my only problem left before being able to submit and receive a perfect score and I would like to understand why there is still a memory leak in that certain line. Thanks again!
Two issues:
new_node shouldn't be a global. It should be local to the load function.
When freeing memory, you don't free the last element in each linked list.
running the posted code through a compiler results in:
gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o"
untitled1.c:24:7: error: variably modified ‘table’ at file scope
24 | node *table[N];
| ^~~~~
untitled1.c: In function ‘check’:
untitled1.c:36:22: warning: implicit declaration of function ‘hash’ [-Wimplicit-function-declaration]
36 | int word_index = hash(word);
| ^~~~
untitled1.c: At top level:
untitled1.c:51:14: error: conflicting types for ‘hash’
51 | unsigned int hash(const char *word)
| ^~~~
untitled1.c:36:22: note: previous implicit declaration of ‘hash’ was here
36 | int word_index = hash(word);
| ^~~~
untitled1.c: In function ‘hash’:
untitled1.c:57:40: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
57 | index = ((index << 5) + index) + tolower(*ptr);
| ^
untitled1.c:60:18: warning: conversion from ‘long unsigned int’ to ‘unsigned int’ may change value [-Wconversion]
60 | return index % N;
| ~~~~~~^~~
untitled1.c: In function ‘load’:
untitled1.c:98:26: warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
98 | int word_index = hash(new_node->word);
| ^~~~
untitled1.c: In function ‘size’:
untitled1.c:121:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
121 | for (int i = 0; i < N; i++)
| ^
untitled1.c:136:12: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
136 | return word_counter;
| ^~~~~~~~~~~~
untitled1.c: In function ‘unload’:
untitled1.c:143:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
143 | for (int i = 0; i < N; i++)
| ^
Compilation failed.
So how can it possibly be giving a 'run time' problem?
When compiling, always enable the warnings, then fix those warnings
There are also several problems with the logic of the posted code, but you really need to get it to cleanly compile (and link) before getting into the logic.
One of the easiest ways to debug the logic is with a debugger, like gdb or an IDE, like visual studio.
I am running apache bench (ab) and ported it with OpenSSL 1.0 support on top of mTCP support
https://github.com/vincentmli/mtcp/commit/642835f786aa642ea0f20fe8db9b09054639453a#diff-02f7a72f514e6e0543e832d37450c251
but it breaks after I upgraded OpenSSL 1.0 to OpenSSL 1.1, I found there are quite a few projects having same problems including libevent, libevent has the fix in https://github.com/libevent/libevent/commit/3e9e0a0d46e4508e8782ec3787c6d86bab63046d
so I borrowed the fix from libevent and applied the code fix below:
#include <openssl/bio.h>
#include "openssl-compat.h"
#define get_last_socket_error() errno
#define clear_socket_error() errno=0
/* clone of openssl crypto/bio/bss_sock.c */
#ifdef HAVE_MTCP
static int mtcp_sock_write(BIO *h, const char *buf, int num);
static int mtcp_sock_read(BIO *h, char *buf, int size);
static int mtcp_sock_puts(BIO *h, const char *str);
static long mtcp_sock_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int mtcp_sock_new(BIO *h);
static int mtcp_sock_free(BIO *data);
int BIO_mtcp_sock_should_retry(int s);
/*
static BIO_METHOD mtcp_methods_sockp = {
BIO_TYPE_SOCKET,
"socket",
mtcp_sock_write,
mtcp_sock_read,
mtcp_sock_puts,
NULL,
mtcp_sock_ctrl,
mtcp_sock_new,
mtcp_sock_free,
NULL,
};
BIO_METHOD *BIO_mtcp_s_socket(void)
{
return (&mtcp_methods_sockp);
}
*/
static BIO_METHOD *mtcp_methods_sockp;
static BIO_METHOD *
BIO_mtcp_s_socket(void)
{
if (mtcp_methods_sockp == NULL) {
mtcp_methods_sockp = BIO_meth_new(BIO_TYPE_SOCKET, "socket");
if (mtcp_methods_sockp == NULL)
return NULL;
BIO_meth_set_write(mtcp_methods_sockp, mtcp_sock_write);
BIO_meth_set_read(mtcp_methods_sockp, mtcp_sock_read);
BIO_meth_set_puts(mtcp_methods_sockp, mtcp_sock_puts);
BIO_meth_set_ctrl(mtcp_methods_sockp, mtcp_sock_ctrl);
BIO_meth_set_create(mtcp_methods_sockp, mtcp_sock_new);
BIO_meth_set_destroy(mtcp_methods_sockp, mtcp_sock_free);
}
return mtcp_methods_sockp;
}
/*
BIO *BIO_mtcp_new_socket(mctx_t mctx, int fd, int close_flag)
{
BIO *ret;
ret = BIO_new(BIO_mtcp_s_socket());
if (ret == NULL)
return (NULL);
BIO_set_fd(ret, fd, close_flag);
ret->ptr = mctx;
return (ret);
}
*/
BIO *BIO_mtcp_new_socket(mctx_t mctx, int fd, int close_flag)
{
BIO *ret;
if(!fd)
return NULL;
ret = BIO_new(BIO_mtcp_s_socket());
if (ret == NULL)
return (NULL);
BIO_set_init(ret, 1);
BIO_set_fd(ret, fd, close_flag);
BIO_set_data(ret, mctx);
return (ret);
}
/*
static int mtcp_sock_new(BIO *bi)
{
bi->init = 0;
bi->num = 0;
bi->ptr = NULL;
bi->flags = 0;
return (1);
}
*/
static int mtcp_sock_new(BIO *bi)
{
BIO_set_init(bi, 0);
BIO_set_num(bi, 0);
BIO_set_data(bi, NULL);
BIO_set_flags(bi, 0);
return (1);
}
/*
static int mtcp_sock_free(BIO *a)
{
if (a == NULL)
return (0);
mctx_t mctx = (mctx_t)a->ptr;
mtcp_close(mctx, a->num);
return (1);
}
*/
static int mtcp_sock_free(BIO *a)
{
if (a == NULL)
return (0);
mctx_t mctx = (mctx_t)BIO_get_data(a);
mtcp_close(mctx, BIO_get_num(a));
return (1);
}
/*
static int mtcp_sock_read(BIO *b, char *out, int outl)
{
int ret = 0;
mctx_t mctx = (mctx_t)b->ptr;
if (out != NULL) {
clear_socket_error();
//ret = readsocket(b->num, out, outl);
ret = mtcp_read(mctx, b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_read(b);
}
}
return (ret);
}
*/
static int mtcp_sock_read(BIO *b, char *out, int outl)
{
int ret = 0;
mctx_t mctx = (mctx_t)BIO_get_data(b);
if (out != NULL) {
clear_socket_error();
//ret = readsocket(b->num, out, outl);
ret = mtcp_read(mctx, BIO_get_num(b), out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_read(b);
}
}
return (ret);
}
/*
static int mtcp_sock_write(BIO *b, const char *in, int inl)
{
int ret;
mctx_t mctx = (mctx_t)b->ptr;
clear_socket_error();
//ret = writesocket(b->num, in, inl);
ret = mtcp_write(mctx, b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_write(b);
}
return (ret);
}
*/
static int mtcp_sock_write(BIO *b, const char *in, int inl)
{
int ret;
mctx_t mctx = (mctx_t)BIO_get_data(b);
clear_socket_error();
//ret = writesocket(b->num, in, inl);
ret = mtcp_write(mctx, BIO_get_num(b), in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_write(b);
}
return (ret);
}
/*
static long mtcp_sock_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
int *ip;
switch (cmd) {
case BIO_C_SET_FD:
mtcp_sock_free(b);
b->num = *((int *)ptr);
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL)
*ip = b->num;
ret = b->num;
} else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return (ret);
}
*/
static long mtcp_sock_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
int *ip;
switch (cmd) {
case BIO_C_SET_FD:
mtcp_sock_free(b);
BIO_set_num(b, *((int *)ptr));
BIO_set_shutdown(b, (int)num);
BIO_set_init(b, 1);
break;
case BIO_C_GET_FD:
if (BIO_get_init(b)) {
ip = (int *)ptr;
if (ip != NULL)
*ip = BIO_get_num(b);
ret = BIO_get_num(b);
} else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
case BIO_CTRL_SET_CLOSE:
BIO_set_shutdown(b, (int)num);
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return (ret);
}
here is the openssl-compat.h
#ifndef OPENSSL_COMPAT_H
#define OPENSSL_COMPAT_H
#include <openssl/bio.h>
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
static inline BIO_METHOD *BIO_meth_new(int type, const char *name)
{
BIO_METHOD *biom = calloc(1, sizeof(BIO_METHOD));
if (biom != NULL) {
biom->type = type;
biom->name = name;
}
return biom;
}
#define BIO_meth_set_write(b, f) (b)->bwrite = (f)
#define BIO_meth_set_read(b, f) (b)->bread = (f)
#define BIO_meth_set_puts(b, f) (b)->bputs = (f)
#define BIO_meth_set_ctrl(b, f) (b)->ctrl = (f)
#define BIO_meth_set_create(b, f) (b)->create = (f)
#define BIO_meth_set_destroy(b, f) (b)->destroy = (f)
#define BIO_set_init(b, val) (b)->init = (val)
#define BIO_set_data(b, val) (b)->ptr = (val)
#define BIO_set_shutdown(b, val) (b)->shutdown = (val)
#define BIO_set_num(b, val) (b)->num = (val)
#define BIO_set_flags(b, val) (b)->flags = (val)
#define BIO_get_init(b) (b)->init
#define BIO_get_data(b) (b)->ptr
#define BIO_get_shutdown(b) (b)->shutdown
#define BIO_get_num(b) (b)->num
#define BIO_get_flags(b) (b)->flags
#define TLS_method SSLv23_method
#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) */
#endif /* OPENSSL_COMPAT_H */
but I got compiling error
make[2]: Entering directory '/usr/src/mtcp/apps/apache_benchmark/support'
/usr/src/mtcp/apps/apache_benchmark/srclib/apr/libtool --silent --mode=compile gcc -g -O2 -pthread -I/usr/src/mtcp/mtcp/lib/ -I/usr/src/mtcp/mtcp/src/include/ -DMULTI_THREADED -I/usr/src/mtcp/mtcp/lib/ -I/usr/src/mtcp/mtcp/src/include/ -DMULTI_THREADED -DLINUX -D_REENTRANT -D_GNU_SOURCE -I/usr/src/mtcp/apps/apache_benchmark/srclib/pcre -I. -I/usr/src/mtcp/apps/apache_benchmark/os/unix -I/usr/src/mtcp/apps/apache_benchmark/include -I/usr/src/mtcp/apps/apache_benchmark/srclib/apr/include -I/usr/src/mtcp/apps/apache_benchmark/srclib/apr-util/include -I/usr/src/mtcp/apps/apache_benchmark/srclib/apr-util/xml/expat/lib -I/usr/lib/include -I/usr/src/mtcp/apps/apache_benchmark/modules/ssl -prefer-non-pic -static -c ab.c && touch ab.lo
ab.c: In function ‘mtcp_sock_new’:
ab.c:547:5: warning: implicit declaration of function ‘BIO_set_num’; did you mean ‘BIO_set_next’? [-Wimplicit-function-declaration]
BIO_set_num(bi, 0);
^~~~~~~~~~~
BIO_set_next
ab.c: In function ‘mtcp_sock_free’:
ab.c:570:22: warning: implicit declaration of function ‘BIO_get_num’; did you mean ‘BIO_get_init’? [-Wimplicit-function-declaration]
mtcp_close(mctx, BIO_get_num(a));
^~~~~~~~~~~
BIO_get_init
..........CUT......
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:547: undefined reference to `BIO_set_num'
.libs/ab.o: In function `mtcp_sock_free':
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:570: undefined reference to `BIO_get_num'
.libs/ab.o: In function `mtcp_sock_ctrl':
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:703: undefined reference to `BIO_get_num'
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:704: undefined reference to `BIO_get_num'
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:695: undefined reference to `BIO_set_num'
.libs/ab.o: In function `mtcp_sock_read':
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:603: undefined reference to `BIO_get_num'
.libs/ab.o: In function `mtcp_sock_write':
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:638: undefined reference to `BIO_get_num'
.libs/ab.o: In function `main':
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:2916: undefined reference to `SSLv3_client_method'
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:2913: undefined reference to `SSLv2_client_method'
/usr/src/mtcp/apps/apache_benchmark/support/ab.c:2978: undefined reference to `CRYPTO_malloc_init'
collect2: error: ld returned 1 exit status
Makefile:38: recipe for target 'ab' failed
make[2]: *** [ab] Error 1
Since I defined BIO_set/get_init/data/shutdown/num in openssl-compat.h, why it only shows undefined reference to `BIO_set/set_num', not others? I am confused
So a foreword, I am new to C, so please forgive any horrifying mistakes my program has.
I am trying to write a program that will take a list of numbers passed in as arguments to the program or contained in a file whose path is passed in.
It stores the numbers into an array, and stores how many numbers there are into the first element of the array. It will only store up to 100 numbers.
It then creates a pthread and passes the pointer to the array to the thread.
The thread is then suppose to sum up the numbers and return the sum back to the main function.
I am experiencing the following issues:
1. It doesn't always happen, but sometimes I get a segmentation fault right before the line of code that says:
printf("Begining to create the thread");
2. My attempts to return the sum isn't working, and after hours of research online, I can't figure out why.
3. When I compile the program, I get the following errors:
gcc -g -o assn3 assn3.c -pthread
assn3.c: In function ‘AddUpNumbers’:
assn3.c:34:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
return (void*)total;
^
assn3.c: In function ‘main’:
assn3.c:96:3: warning: passing argument 1 of ‘pthread_join’ makes integer from pointer without a cast [enabled by default]
pthread_join(&functionThread, &total);
^
In file included from assn3.c:12:0:
/usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’
extern int pthread_join (pthread_t __th, void **__thread_return);
^
assn3.c:97:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘void *’ [-Wformat=]
printf("The total returned by the thread is %d", total);
^
Here's my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NO_ARGS 1
#define ONLY_SINGLE_ARG 2
#define PATH_TO_READ_FROM 1
#define MAX_NUMBERS 101
#define MAX_CHAR_INPUT 255
#define COUNT_LOCATION 0
void* AddUpNumbers(void* arrayPointer) {
printf("Created the pthread!");
int* numbersArray = (int*)arrayPointer;
int count = numbersArray[COUNT_LOCATION];
int total = 0;
int i = 1;
while (i < count) {
total = total + numbersArray[i];
}
printf("The total to be returned is %d", total);
return (void*)total;
}
int main(int argc, char* argv[]) {
FILE * numbersFile = NULL;
int count = 0;
int numberArray[MAX_NUMBERS];
//Initialize the Array
int i = 0;
while (i < MAX_NUMBERS) {
numberArray[i] = 0;
i = i + 1;
}
if (argc == NO_ARGS) {
printf("Usage: # or file path, #, #, ..., #\n");
} else if (argc == ONLY_SINGLE_ARG) {
numbersFile = fopen(argv[PATH_TO_READ_FROM], "r");
if (numbersFile != NULL) {
char buff[MAX_CHAR_INPUT];
i = 1;
count = 0;
while (i < MAX_NUMBERS) {
if (fscanf(numbersFile, "%s", buff) != EOF) {
numberArray[i] = atoi(buff);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
} else {
break;
}
}
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Error: Could not open file!\n");
return -1;
}
} else if (argc < MAX_NUMBERS + 1) {
i = 1;
count = 0;
while (i < argc) {
numberArray[i] = atoi(argv[i]);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
}
printf("See if error happens after this");
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Too many numbers! This program can only add up to: %d numbers.\n", MAX_NUMBERS);
return -1;
}
printf("Begining to create the thread");
pthread_t functionThread;
int creationSuccess = 0;
void* total;
creationSuccess = pthread_create(&functionThread, NULL, AddUpNumbers, (void*)numberArray);
if (creationSuccess == 0) {
pthread_join(&functionThread, total);
printf("The total returned by the thread is %d", *((int)total));
} else {
printf("Something went wrong.\n");
}
if (numbersFile != NULL) {
fclose(numbersFile);
}
return 0;
}
My Makefile looks like this:
assn3: assn3.c
gcc -g -o assn3 assn3.c -pthread
You should be very wary of compiler warnings. Either clean them up or understand very well why they are ok. Pay special attention to warnings about data type mismatches.
In this case this warning probably explains the main problem:
In file included from assn3.c:12:0:
/usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’
extern int pthread_join (pthread_t __th, void **__thread_return);
^
You are (creating and) passing a pointer to your pthread_t object as the first argument of pthread_join(), but unlike pthread_create(), pthread_join() expects you to pass the pthread_t itself, not a pointer to it. All manner of havoc (technically, "undefined behavior") will ensue.
UPDATE: Additionally, the second argument you are passing to pthread_join() is an uninitialized pointer to void. If pthread_create() tries to write anything where it points then who knows what happens (undefined behavior again). You are expected to pass a valid pointer to the location where the result is to be written. In this case, that would be &total.
The syntax of pthread_create is:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, *(*start_routine) (void *), void *arg);
pthread_t - is id of thread. So create variable pthread_t id, or array of values if you have a lot of threads, like pthread_t id[THREAD_NUM];
Then your func will looks like:
pthread_create(&id[i], NULL, &functionThread, (void*)numberArray);
With pthread_join(&functionThread, total);
The same thing.
int pthread_join(pthread_t thread, void **value_ptr);
So you join must look like:
pthread_join(&id[i], total);
I don't understand why my C compiler is throwing a dirent error. I initialized everything, or at least I thought I did, in according to the man page. And yet I am still getting thrown a dirent error. It keeps saying expected int (*)(const struct dirent *) but argument is of type 'int (*)(struct dirent *)'
My code:
extern int alphasort();
int count, i;
struct direct **files;
if(!(getcwd(pathname, sizeof(pathname))))
{
die("Error getting pathname\n");
}
printf("Current Working Directory = %s\n", pathname);
count = scandir(pathname, &files, file_select, alphasort);
if (count < 0)
{
die("No files in this directory.\n");
}
else
{
printf("Number of files = %d\n", count);
for (i = 1; i < count+1; i++)
{
printf("%s ",files[i-1]->d_name);
printf("\n");
}
return 1;
}
pathname = char pathname[MAXPATHLEN];
file_select =
int file_select(struct direct *entry)
{
if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0))
return (FALSE);
else
return (TRUE);
}
You need to change your callback function so its argument matches what is expected:
int file_select(const struct direct *entry)
{
.
.
.
}