I am doing simple sigaction example to practice C, but when I try to compile my code, it claims that struct sigaction doesn't exist [1].
When I checked out some old code I had produced I saw that I had added some POSIX string at the very top of the file [2]. But when I read the manual for sigaction (man 2 sigaction) there is nothing about _POSIX_SOURCE in it, the closest being _POSIX_C_SOURCE which doesn't work. How and when do I know which POSIX is the be used? When I try simple code that others have suggested, which is without the _POSIX_SOURCE it doesn't work.
[1]
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sa_handler(int signum)
{
printf("The signal has been replaced with this useless
string!\n");
exit(0);
}
int main(void)
{
struct sigaction sa = {.sa_handler = sa_handler};
int sigret = sigaction(SIGINT, &sa, NULL);
while(1);
return 0;
}
[2]
#define _POSIX_SOURCE
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sa_handler(int signum)
{
printf("The signal has been replaced with this useless
string!\n");
exit(0);
}
int main(void)
{
struct sigaction sa = {.sa_handler = sa_handler};
int sigret = sigaction(SIGINT, &sa, NULL);
while(1);
return 0;
}
When I compile the first example the result are these error messages.
sigaction.c: In function ‘main’:
sigaction.c:13:12: error: variable ‘sa’ has initializer but
incomplete type
struct sigaction sa = {.sa_handler = sa_handler};
^~~~~~~~~
sigaction.c:13:29: error: ‘struct sigaction’ has no member named
‘sa_handler’
struct sigaction sa = {.sa_handler = sa_handler};
^~~~~~~~~~
sigaction.c:13:42: warning: excess elements in struct initializer
struct sigaction sa = {.sa_handler = sa_handler};
^~~~~~~~~~
sigaction.c:13:42: note: (near initialization for ‘sa’)
sigaction.c:13:22: error: storage size of ‘sa’ isn’t known
struct sigaction sa = {.sa_handler = sa_handler};
^~
sigaction.c:14:18: warning: implicit declaration of function
‘sigaction’ [-Wimplicit-function-declaration]
int sigret = sigaction(SIGINT, &sa, NULL);
^~~~~~~~~
when I read the manual for sigaction (man 2 sigaction) there is nothing about _POSIX_SOURCE in it
From man sigaction:L
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
From future_test_macros(7):
_POSIX_SOURCE
Defining this obsolete macro with any value is equivalent to
defining _POSIX_C_SOURCE with the value 1.
Since this macro is obsolete, its usage is generally not doc‐
umented when discussing feature test macro requirements in
the man pages.
So _POSIX_SOURCE is equivalent to _POSIX_C_SOURCE 1 and is obsolete.
How and when do I know which POSIX is the be used?
From man future_test_macros:
Specification of feature test macro requirements in manual pages
When a function requires that a feature test macro is defined, the
manual page SYNOPSIS typically includes a note [....]
So you should check SYNOPSIS section in the manual page of the function/feature you are interested in. For example for man sigaction:
sigaction(): _POSIX_C_SOURCE
siginfo_t: _POSIX_C_SOURCE >= 199309L
So you need to define _POSIX_C_SOURCE for sigaction() and _POSIX_C_SOURCE greater or equal to the value of 199309 for siginfo_t.
You need to define a positive integer for _POSIX_C_SOURCE. For sigaction, it needs to be atleast:
#define _POSIX_C_SOURCE 199309L
Look the the documentation for which POSIX version to use.
You need to add <features.h> before <signals.>, as the features.h contains #define _POST_C_SOURCE with latest value for compatibility purpose.
Related
I have some code where two 2 threads modify the value of the same variable but with two different functions. So I decided to use a common mutex. That for: I initialised it globally :
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define perror_pthread(ret, msg) \
do { errno = ret; perror(msg); } while (0)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*define a mutex-object */
pthread_mutex_init(&mutex,NULL); /*initialise this mutex object with default values */
I get an error message :
error: expected declaration specifiers or ‘...’ before ‘&’ token
pthread_mutex_init(&mutex,NULL); /*initialise this mutex object with default values */
^
I don't know if that's a good practice, but I feel like both functions should have the same mutex in order to be informed when there is lock
pthread_mutex_init is a function and C forbids expressions (i.e. function calls) at the file scope.
Either use static initializer or put pthread_mutex_init(...) into beginning of main().
I want to write a program using the new SCHED_DEADLINE scheduling policy available since Linux 3.14.
I start out with a simple program trying to use the sched_setattr function.
#include <sched.h>
int main(void)
{
// struct sched_attr attr;
// attr.size = sizeof(struct sched_attr);
// attr.sched_policy = SCHED_DEADLINE;
sched_setattr(0, (void*)0, 0);
return 0;
}
However when compiling I get the following error:
$gcc dead.c
dead.c: In function ‘main’:
dead.c:8:2: warning: implicit declaration of function ‘sched_setattr’ [-Wimplicit-function-declaration]
sched_setattr(0, (void*)0, 0);
^~~~~~~~~~~~~
/tmp/ccGxWxZE.o: In function `main':
dead.c:(.text+0x19): undefined reference to `sched_setattr'
collect2: error: ld returned 1 exit status
My system is running Ubuntu 16.10 Yakkety, with kernel 4.8.0-59-generic. The sched.h file included is found in /usr/include/sched.h and is provided by the package libc6-dev. This headerfile does not contain the function sched_setattr and friends that I am trying to use.
However the kernel (and kernel headers) I have installed comes with a sched.h header file containing the definitions I need. It is located at /usr/src/linux-headers-4.8.0-58/include/linux/sched.h, on my system.
So I naively think lets just build against the newer linux headers instead of the libc6-dev provided headers. My program will only run on this or newer kernels, but that is just fine.
I modify the first line to be: #include <linux/sched.h> and execute:
gcc -I/usr/src/linux-headers-$(uname -r)/include -I/usr/src/linux-headers-$(unam -r)/arch/x86/include dead.c
Now I am getting page after page of errors and warning. This does not seem the way to go.
What is the correct way to build a userspace program against a newer Linux headers than those that are provided by libc?
And subsequently how do I build the program above?
sched_setattr() is a syscall and doesn't seem to have one-to-one libc wrapper. You could do the wrapper yourself, something like this:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <linux/sched.h>
#include <sys/syscall.h>
#include <sys/types.h>
struct sched_attr {
uint32_t size; /* Size of this structure */
uint32_t sched_policy; /* Policy (SCHED_*) */
uint64_t sched_flags; /* Flags */
int32_t sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */
uint32_t sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) */
/* Remaining fields are for SCHED_DEADLINE */
uint64_t sched_runtime;
uint64_t sched_deadline;
uint64_t sched_period;
};
static int sched_setattr (pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
return syscall (SYS_sched_setattr, pid, attr, flags);
}
int main (int argc, char *argv[])
{
struct sched_attr attr;
int res;
memset (&attr, 0, sizeof (struct sched_attr));
attr.size = sizeof (struct sched_attr);
res = sched_setattr (getpid (), &attr, 0);
if (res < 0) {
perror ("sched_setattr");
return 1;
}
return 0;
}
Looking at the errors reported when trying to include kernel header files required to get the definition of struct sched_attr and reading the comments found by Googling "kernel headers in user space", I really can't suggest trying to include kernel header files just for this.
I am trying to make a C program that uses named pipes to communicate with a C++ program on a Raspberry Pi 3.
The warning that GCC is spitting out when I compile some code of mine:
/home/pi/BluetoothTest/btooth.c|76|warning: implicit declaration of function ‘mknod’ [-Wimplicit-function-declaration]|
Here is the code from for the function, including the #if above it:
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
and here are the includes that I have in the file:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/rfcomm.h>
//#include <linux/stat.h>
The program attempts to create the pipe here:
umask(0);
fifo = mknod(PIPE_LOC, S_IFIFO|0666, 0);
fp = fopen(PIPE_LOC, "w");
fifo is an int that isn't used anywhere else and fp is a FILE* to the pipe. Some debugging that I have done shows that fifo has a value of -1 after mknod runs, likely because of the compiler not seeming to be able to find the implementation of the function.
How do I make it so that GCC knows where to find the implementation of mknod?
As you can see that for declaration of mknod() function to stay after preprocessing stage, one of three macros (__USE_MISC, __USE_BSD, __USE_XOPEN_EXTENDED) should be defined. Otherwise, declaration of mknod() will be removed during preprocessing stage.
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
You can use compiler options: -std=gnu99 -D_GNU_SOURCE or you can define these macros on your own and place them above header file inclusion.
I think you're missing a definition of some feature test macro required for the respective headers to define mknod. According to the Linux Programmer's Manual for the function (man 2 mknod) the macros for glibc are:
mknod():
_XOPEN_SOURCE >= 500
|| /* Since glibc 2.19: */ _DEFAULT_SOURCE
|| /* Glibc versions <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE
Try adding -D_XOPEN_SOURCE=500 to your compile flags to see if that helps.
If i compile the below program with std=c99, i get an error, but the program compiles fine without the c99 flag. Why?
#include <signal.h>
void x()
{
sigset_t dd;
}
int main(void)
{
x();
return 0;
}
jim#cola temp]$ gcc -std=c99 blah.c -o blah
blah.c: In function ‘x’:
blah.c:9: error: ‘sigset_t’ undeclared (first use in this function)
blah.c:9: error: (Each undeclared identifier is reported only once
blah.c:9: error: for each function it appears in.)
blah.c:9: error: expected ‘;’ before ‘dd’
Because sigset_t is not part of <signal.h> in standard C and you requested strict standards compatibility with -std=c99. That is, a strictly standard C program can do:
#include <signal.h>
int sigset_t;
int main(void) { return 0; }
and expect it to work.
sigset_t is not in C99 standard, but it is available in POSIX. You can define _POSIX_SOURCE or _POSIX_C_SOURCE to make sigset_t available.
Here is the definition:
#define _NSIG 64
#define _NSIG_BPW 32
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef unsigned long old_sigset_t; /* at least 32 bits */
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t;
Also see What does #define _POSIX_SOURCE mean?
Although including <signal.h> I get an error saying that struct sigaction is an incomplete type.
I have no Idea what to do with it.
Please help
#include <signal.h>
struct sigaction act;
int main(int argc, char** argv)
{
int depth;
/* validate arguments number*/
if(argc < 2)
{
printf("fatal error: please use arguments <MaxChild> <MaxDepth>\n");
exit(1);
}
/* register the realtime signal handler for sigchld*/
/*173*/
memset(&act,0,sizeof(act));
act.sa_handler = sigproc;
sigaction(SIGCHLD, /* signal number whose action will be changed */
&act, /* new action to do when SIGCHLD arrives*/
NULL); /* old action - not stored */
srand(time(NULL));
depth = rand() % atoi(argv[2]); /* [0 maxDepth]*/
RecursiveFunc(atoi(argv[1]), depth);
return 0;
}
The error messages:
proc.c: In function ‘main’:
proc.c:173:22: error: invalid application of ‘sizeof’ to incomplete type ‘struct sigaction’
proc.c:174:2: error: invalid use of undefined type ‘struct sigaction’
cc1: warnings being treated as errors
proc.c:175:2: error: implicit declaration of function ‘sigaction’
Just
#define _XOPEN_SOURCE 700
before any other line in your code, or compile with the -D option to define the preprocessor symbol
gcc ... -D_XOPEN_SOURCE=700 ...
I resolved this by changing the C standard that I was using with gcc.
I changed: gcc -std=c99 ...
to this: gcc -std=gnu99 ...