Linux C快速指南
介绍Linux环境C语言开发,以问题为切入点,以代码为展示的形式介绍Linux系统开发知识。
程序猿Ricky的日常干货
擅长扫地、打杂、开车。。
展开
-
Linux应用层时间和定时器
时间Linuxtime_t time(time_t *ptr);int gettimeofday(struct timeval *restrict tp, struct timezone *gz); int settimeofday(const struct timeval *tv, const struct timezone *gz);posix#include ...原创 2019-07-30 11:50:28 · 397 阅读 · 0 评论 -
标准输入,标准输出和标准错误
当我们使用文件描述符进行操作时,需要操作标准输入、标准输出、标准错误,可以包含如下头文件:#include <unistd.h>这个头文件中定义了标准设备:/* Standard file descriptors. */#define STDIN_FILENO 0 /* Standard input. */#define STDOUT_FILENO 1 ...原创 2019-03-19 17:48:04 · 5336 阅读 · 0 评论 -
linux系统中的时间及操作函数
(一)Linux系统中的时间rtc由rtc芯片提供的时间,可以转换为格林尼治时间,linux中把这一类时间称为wall time,墙上时间。rtc时间由rtc芯片来维护更新,它通常由一个专门的计时硬件来实现,软件可以读取该硬件来获得年月日、时分秒等时间信息。rtc时间是可持续计时的,通常硬件上会加上一个后备电池供电,这样即使系统关闭,rtc时间依然是正常更新的,这样就可以保证...原创 2016-05-17 10:05:19 · 3111 阅读 · 0 评论 -
Linux posix消息队列使用详解及注意事项
创建标志O_CREAT这个标志是在创建消息队列时需要传入的打开标志。它的含义是,如果该消息队列不存在,那么就创建它,它的隐含含义就是如果该消息队列是存在的,那么O_CREAT不起作用,而仅仅执行打开操作。编译测试代码后重复运行该执行文件,都次都会成功打开,打印如下:$ ./posix_msq [6590] INFO: mq_open successO_EXCL一般这个标志是和O_C...原创 2019-04-13 22:17:07 · 2457 阅读 · 0 评论 -
Linux自定义timer实现(基于setitimer)
概论不管是用户空间的程序开发,还是内核空间的程序开发,很多时候都需要有定时器的支持,定时器属于程序开发中的基本组件。定时器一般按照使用场景分为两种类型:1.Single-Shot Timer2.Repeating Timer其中第一种定时器,从注册到终止只执行一次,而第二种定时器,在每次执行完以后,自动重新开始。本质上,可以认为 Repeating Timer 是在 Single-Shot Time原创 2016-05-17 13:57:58 · 1217 阅读 · 0 评论 -
Linux SIGABRT和abort()函数
SIGABRT被阻塞还有一个信号SIGABRT要特别说明,表示异常终止信号,当系统调用abort()时会发送SIGABRT信号,那么如果阻塞了该信号会影响abort()函数的使用吗?经过测试,事实证明并不会,因为abort()的内部实现已经确保了该函数调用器件,SIGALRM信号不会被阻塞。#include <stdio.h>#include <stdlib.h>...原创 2019-04-12 10:10:45 · 12898 阅读 · 5 评论 -
Linux应用层定时器
alarmalarm会设置一个定时器,当时间到期后会触发SIGALRM信号,该信号可能会打断系统调用的执行,它使用的定时器和setitimer对应的ITIMER_REAL是同一个。#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#inclu...原创 2019-04-11 12:59:20 · 796 阅读 · 0 评论 -
被中断的系统调用
我们知道系统调用一旦阻塞,当信号到来是会中断此系统调用执行的,但是如下情况是不会对系统调用产生影响:1.单个进程阻塞信号不会对后续系统调用产生中断行为。2.线程中通过pthread_sigmask阻塞信号后,对该进程发送的信号是不影响该线程的系统调用的,会被发送到其他线程处理。多线程的示例如下:#include <unistd.h>#include <stdlib.h&...原创 2019-04-10 17:01:27 · 949 阅读 · 0 评论 -
多线程与信号
多线程环境的信号递送在一个单进程中,信号会打断进程的执行,并且递送到进程中处理,而对于多线程环境,信号会递送给其中的一个线程,这个被递送的线程是不确定的。每个线程存在自己的信号屏蔽字,可以通过如下函数设置:int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);该函数设置线程对应的信号屏蔽字,被屏蔽的信号会被挂...原创 2019-04-11 10:10:38 · 4704 阅读 · 0 评论 -
Linux -- POSIX IPC
信号量#include <fcntl.h> /* For O_* constants */#include <sys/stat.h> /* For mode constants */#include <semaphore.h>sem_t *sem_open(const char *name, int oflag);s...原创 2019-04-04 18:25:24 · 292 阅读 · 0 评论 -
system v IPC代码示例
消息队列#include <sys/msg.h>#include <sys/ipc.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <...原创 2019-04-03 20:33:10 · 216 阅读 · 0 评论 -
Linux -- system V IPC
每个system v IPC结构对应着一个标识符,标识符是一个非负的整型数据,这是一个内部名,对应的外部名为键值,多个进程通过共同的键值可以获取到同一个标识符从而能够操作同一个IPC结构。键值IPC_PRIVATE键值属于匿名键值,一般用于父子进程IPC的情况。也可以把返回的标识符(整型值)保存到外部的文件中,由不相关进程获取从而进行IPC。头文件显式定义键值(key_t),它存在的问题是...原创 2019-04-03 11:29:22 · 314 阅读 · 0 评论 -
进程同步的两种实现
在前文《Linux – 进程控制》博客中,我曾提到过父子进程之间的同步有两种方法:分别是基于管道和信号实现。为什么需要进程的同步,当我们创建一个新进程时,为了保证父子进程的运行按照我们预期的时序进行,所以需要加入同步机制。下面直接以代码示例来实现两种同步方式。基于管道实现的进程同步#include <unistd.h>#include <stdio.h>#incl...原创 2019-04-02 17:38:57 · 2772 阅读 · 0 评论 -
Linux -- pipe管道
函数接口#include <unistd.h>int pipe(int fd[2]);成功返回0,错误返回-1该函数会创建一个管道,其中返回的fd[0]为读而打开,fd[1]为写而打开,一般用法是父进程利用pipe创建管道后,使用fork创建子进程,这样父子进程各有一对fd用于读取和写入管道,为了进程间的通信,需要各自保留一个读接口和一个写接口用于交换信息。它的特点:...原创 2019-04-01 14:44:37 · 921 阅读 · 0 评论 -
Linux -- FIFO命名管道
接口#include <sys/stat.h>int mkfifo(const char *path, mode_t mode);int mkfifoat(int fd, const char *path, mode_t mode);成功返回0,出错返回-1FIFO也叫命名管道,可以由不相关的进程使用。它会在文件系统中创建一个FIFO类型的文件,存在于路径名path的位...原创 2019-04-02 12:42:55 · 603 阅读 · 0 评论 -
Linux -- 进程间通信(IPC)机制
Linux系统的IPC方式有如下几种:pipe管道它是unix系统中最古老的IPC形式,所有的UNIX系统都提供此种通信机制,它有以下两种局限性:(1)半双工。现在,虽然某些系统提供了全双工的管道,但是为了可移植性,我们绝不能假定系统支持全双工管道。(2)管道只能在具有公共祖先的两个进程之间使用。通常,一个管道由一个进程创建,在进程调用fork后,这个管道就能在父子进程之间使用了。FIF...原创 2019-03-29 18:00:11 · 345 阅读 · 0 评论 -
Linux -- signal信号
简介信号是操作系统提供了一种处理异步事件的方法,每个用户进程都会接受到信号,并且可以注册信号处理函数,当信号到来时会执行注册的处理函数。当信号到来是可以告诉内核使用如下三种方式处理对应的信号:忽略该信号。大多数信号都可以做此操作,除了SIGKILL和SIGSTOP这两个信号,代码中信号处理函数注册为SIG_IGN可以忽略信号。捕获信号。注册信号处理函数为自己想要执行的用户函数,同样的,S...原创 2019-03-29 11:58:24 · 658 阅读 · 0 评论 -
Linux应用层时间函数
time时间函数#include <time.h>time_t time(time_t *ptr);这个函数返回从UNIX新纪元( 1970年1月1日00:00:00 UTC )开始到现在经过的秒数,并且是按照UTC协调时间进行计算,统称为日历时间。它的精度是秒。clock_gettime#include <sys/time.h>int clock_get...原创 2019-03-28 14:55:55 · 398 阅读 · 0 评论 -
Linux -- getopt参数解析
getopt函数#include <unistd.h>int getopt(int argc, char * const argv[], const char *optstring);extern char *optarg;extern int optind, opterr, optopt;getopt函数需要传入对应的argc和argv参数表,还...原创 2019-03-28 10:56:50 · 533 阅读 · 0 评论 -
Linux -- 进程控制
进程id和用户id#include <unistd.h>pid_t getpid(void); //返回当前进程的idpid_t getppid(void); //返回父进程的iduid_t getuid(void); //返回实际用户iduid_t geteuid(void); //返回有效用户idgid_t getgid(void); //返回实际组id...原创 2019-03-27 15:44:43 · 196 阅读 · 0 评论 -
Linux fcntl 函数详解
接口#include <fcntl.h>int fcntl(int fd, int cmd, ...);返回值:正确返回值根据命令码而定,错误返回-1。fcntl是用来修改已经打开文件的属性的函数,包含5个功能:复制一个已有文件描述符,功能和dup和dup2相同,对应的cmd:F_DUPFD、F_DUPFD_CLOEXEC。当使用这两个cmd时,需要传入第三个参数...原创 2019-03-26 19:37:33 · 8795 阅读 · 0 评论 -
系统限制和选项:sysconf 函数详解
Linux系统的实现需要遵循很多个标准,比如ANSI C标准,POSIX标准,XSI标准,每个标准都有各自的限制和选项,标准中规定有一些内容是必须的,一些是可选的。当我们的应用程序设计遵循标准中的选项和限制,那么就可以达到最大化的可移植性。静态定义不管是限制还是选项,都是支持静态和动态获取的,也有一些只能在系统运行后才能确定其值的,那么就只有通过动态去获取了。对于静态定义的系统限制和选项,宏定...原创 2019-03-25 20:04:29 · 2295 阅读 · 0 评论 -
Linux rlimit 函数详解
简介每个进程在运行时系统不会无限制的允许单个进程不断的消耗资源,因此都会设置资源限制。Linux系统中使用resource limit来表示,每个进程都可以设置不同的资源限制,当前进程和其以后fork的子进程会遵循此限制,而其他进程不受当前进程条件的影响。ulimit命令ulimit是一个shell内建的命令:ulimit 是 shell 内建通过该命令,我们可以设置当前shell环境...原创 2019-03-25 16:33:48 · 11744 阅读 · 0 评论 -
POSIX记录锁
假设一种情况,如果有两个进程同时操作同一个文件,那么最后这个文件的状态会是如何?在Linux系统中,是允许多个进程同时操作一个文件的,而文件的状态是由最后一个修改进程决定的。但是如果想要保证当前进程的修改是排他的,比如操作一个数据库文件,该怎么办呢?这时就可以使用记录锁功能保证对文件的操作是排他的,独占的。类UNIX系统中,存在很多种记录锁的实现,本文主要介绍POSIX.1标准的记录锁,POS...原创 2019-03-22 15:58:34 · 658 阅读 · 0 评论 -
如何判断当前的进程是否以root权限运行?
当前登录系统的用户叫做实际用户,而实际运行的进程是以有效用户ID来进行访问权限管理的,正常情况下有效用户就是实际用户,但是如果我们使用了sudo或者使能了设置用户ID位,按照前面文章的介绍,这个有效用户是可能改变的,比如使用sudo执行,进程的有效用户ID就会变为root,那么此进程就相当于具有了root权限。如果我们的程序只允许使用root运行,那么该如何设计呢?C语言程序设计#inclu...原创 2019-03-21 19:17:01 · 6118 阅读 · 0 评论 -
Linux守护进程设计
守护(daemon)进程是为系统提供某种服务的进程,跟随系统启动时启动,在系统关闭时才终止,没有控制终端,属于后台运行的进程。它的设计有如下一些规则和惯例:1.设置umask(0),umask设置的是拒绝的访问权限位,和chomd命令正好相反,为了防止由父进程继承该umask,这里需要把默认文件模式的创建屏蔽字设置为0,也就是不拒绝任何权限设置。2.调用fork(),然后使父进程退出exit,...原创 2019-03-20 20:24:38 · 571 阅读 · 0 评论 -
设置用户ID和设置组ID
与进程相关的ID有如下几个:1.实际用户ID、实际组ID2.有效用户ID、有效组ID、附属组ID3.保存的用户ID、保存的组ID第一组标识我们实际的ID,比如登录shell使用的ID;第二组是进程运行时用于判断文件访问权限的ID,这个是跟访问权限息息相关的;第三组是当我们的ID发生变化时保存的值,方便我们找回。正常情况下实际ID和有效ID是相等的,但是如果我们配置了设置用户ID和设置组...原创 2019-03-20 17:31:36 · 1521 阅读 · 0 评论 -
Linux错误处理(errno)
Linux系统函数失败后都会返回一个负值,并且整形变量errno通常被设置为错误码。我们在使用错误码时,需要包含如下头文件#include <errno.h>errno只在函数返回错误时才有意义,当函数执行正常返回时并不会重置errno,因此此时的errno是不能作为错误处理的。errno是一个int型变量,除了直接使用该变量,还有两个和其相关的API可以方便的查看错误类型:...原创 2019-03-19 16:43:46 · 3312 阅读 · 0 评论 -
Core Dump调试
环境本文以笔者操作系统ubuntu14.04 LTS为例介绍core dump功能。首先查看系统是否使能了core dump功能:$ ulimit -c0返回0表示没有使能,我们需要使能该功能:ulimit -c 1示例#include <unistd.h>#include <stdio.h>#include <errno.h>int...原创 2019-03-19 15:12:31 · 1647 阅读 · 0 评论 -
Linux程序动态库的加载
查看可执行文件中依赖的动态库:$ readelf -d /bin/shDynamic section at offset 0x1ca88 contains 27 entries: 标记 类型 名称/值 0x0000000000000001 (NEEDED) 共享库:[libc.so.6] 0x0000...原创 2019-03-18 20:24:43 · 5118 阅读 · 0 评论 -
Linux系统默认PATH环境变量的设置
当系统启动后,想要运行一个程序,大部分情况下我们都是直接使用程序名即可运行,那是因为系统中的PATH环境变量已经添加了程序所在的目录,程序加载器会查找PATH环境变量来确定该程序所在的绝对路径。init进程中的实现系统在启动时第一个运行的用户空间进程叫init,init进程在启动时会去配置PATH环境变量,而其他用户进程都是由init进程fork产生,所以其他进程都会继承该默认的PATH配置了...原创 2019-03-18 18:53:24 · 4867 阅读 · 0 评论 -
Linux C快速指南--如何获知系统平台的字节序
字节序简单的说,指的就是数据在机器上存储的排序方式,一般分为两种:大字节序(big endian)和小字节序(little endian)。举个例子:一个2 bytes的数字0x0201存放在我们的系统中,按照数学的理解这个数字的低字节0x01,高字节是0x02,但是如果把这个数字存储到我们的机器上,就会分为两种情况。如果在小字节序的机器上存储,那么低地址处存放的就是0x01,高地址处存放的就是...原创 2018-11-26 16:32:33 · 776 阅读 · 0 评论