常用Linux系统编程API

目录

1.常用文件操作函数

2.进程相关函数和常识:

    3.进程间通信:

    4.线程:


Linux(ubantu)系统编程笔记

1.常用文件操作函数


open(char* path,int flag):
    return:为文件描述符,是一个整形数。 
    flag:是打开模式
write(int fd,const void *buf,size_t count):
    return写入的字节数
    fd:是文件描述符
    buf:是任意类型的指针
    count:是要写入的字节数
read(int fd,const void *buf,size_t count):
    return读出的字节数
    fd:是文件描述符
    buf:是任意类型的指针
    count:是要读出的字节数
close(int fd):
    传入文件描述符即可.


[一些常识]:
    1.fopen fwrite fread 这一系列的函数和上述功能相同,但是使用方法会不一样。
    从根本的说区别在于:这些函数是c语言标准的API,而上述的函数是linux内核里的函数。
    2.main函数的完整写法为:int main(char argc,char **argv)/int main(char argc,char *argv[]),
    其中argc是参数总数,argv是指针数组其中从argv[1]开始指向第一个参数.

2.进程相关函数和常识:


fork()与vfork():
    它们都是用于创建一个子进程,子进程会和父进程共享从fork函数开始往下所有代码也包括这个函数本身,所以也就引申出了这个函数的一个特点——它会返回两次。
    当返回值为0时表示这是父进程执行,否则为子进程。
    它们的不同在于,vfork()函数会等待子进程执行结束后在执行父进程,而fork()同时进行,这就引申出了第一个概念:僵尸进程。
wait(int *waitstatus):
    该函数会阻塞父进程直到收到子进程结束码为止。

execl家族函数:
execl();execlp();execv();execvp;
它们的功能比较重复,理解execl本身的用法就基本够用了:
execl(char *pathname,const char *arg ....):
    此函数一般在子进程中调用,它会调用可执行程序或者文件直接覆盖该进程,也就是说执行该函数后如果执行成功将不会有返回值。
    *pathname:可执行程序或文件路径 
    *arg:执行程序需要传入的参数 比如这个可执行程序传入的是系统的cp指令,那么这里就要传file1的路径,然后传file2的路径。
    另外:参数的结尾必须为NULL
execlp():
    和上述一样,唯一不同就是p同PATH表示环境变量,第一个参数可以传非绝对路径.
    
system(const char* command):
    这个函数说白了就是对execl函数的一个高级封装,不用传乱七八糟的参数,直接给命令就这能执行,并且用execl函数时执行成功不会返回,也就是说原函数调用此函数后的代码全都不会执行,
    但是使用system会执行。
popen(const char* command,char *type):
    和system一样,唯一不同就是它在调用可执行程序时会创造一个管道,这样可以获取执行命令后的信息。
    *type:r或者w,这决定它的返回值是一个标准的输入流还是输出流。

[一些常识]:
    僵尸进程:指没有被父进程收集退出码就已经退出了的子进程。
    孤儿进程:子进程未结束但是父进程已经结束的进程,这样的进程最终会被init进程回收,pid为1。


    
3.进程间通信:


[有名管道和无名管道]:
int piepe(int fd[2]):
    无名管道创建函数,管道本质上就是一种文件,但是无名管道所创建的文件不存在于文件管理系统中。
    其中 fd[0]用读而打开,fd[1]用于写而打开。另外,无名管道只能用于有血缘关系的进程通信,说白了就是子进程和父进程或者同一父进程下的子进程。
int mkfifo(const char* pathname,mode_t mode):
    有名管道,从参数就能看出来是创建一个文件用于通信,这个文件是确实存在于文件系统中的。进程利用该文件调用read和write函数即可通信。
    有名管道可以任意进程之间通信。其中,mode在默认情况下设定为阻塞,即当一个进程单方面进行读或写时,当没有对应进程进行写或者读时会阻塞,直到有为止。
    注意:打开的文件必须不存在。


[消息队列]:
须知四个函数:
msgget(key_t ket,int flag):
    获取消息队列,key是一个索引用于寻找队列。flag相当于模式,当flag=IPC_CREAT时如果找不到则会创建一个队列,当创建成功时return 队列的ID。
msgsnd(int msgid,const void *buf,size_t size,int flag):
    发送消息到队列中,其中buf是对应消息,size是大小。成功return消息长度。
msgrcv(int msgid,const void *buf,size_t size,long type,int flag):
    接收消息,和写入一样,唯一不同的是type表示查询的顺序,
    type:== 0 查询队列中第一个消息
          > 0    返回type类型的第一个消息。
    msgctl(int msgid,int cmd,struct msqid_ds *buf);
    其中:key的值如果用于创建可以用ftok(const char* filename,int id)函数,来创建一个美观的,原理是用当前文件的结点数和一个任意id组合成一个十六进制数。

[共享内存]:
int shmget(key_t key,size_t size,int flag):
    创建共享内存
    size:内存字节大小,比如写成1024*4就是4M。
    return:返回共享内存的标识符即shm_id
void shmat(int shm_id,const void *addr,int flag):
    将内存映射进程序占用的cpu内存中来使用,return一个只想共享内存存储地方的一个指针。
    参数:
    *addr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
    id:共享内存标识符
int shmdt(void *shmaddr):
    断开映射连接
    shmaddr:连接的共享内存的起始地址
int shmctl(int id,int cmd,struct shmid_ds *buff):
    控制内存函数
    id:略
    cmd:
    IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
    IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
    IPC_RMID:删除这片共享内存
[一些常识]:
    1.共享内存的写入写出方式和单片机串口的方式一样,就是使对应内存比如buff = "abcd"。
    读就干脆在printf里用%S对应即可。

[信号]:
int kill(pid_t pid, int sig):
    pid > 0,该函数会向PID为pid的进程发送信号值为sig的信号。
    pid = 0,该函数会向当前进程隶属的进程组下所有的进程发出信号值为sig的信号,包括这个进程自己。
    sig是具体信号
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler):
    sighandler_t是一个指向函数的指针,要求参数列表只有一个int参数,并且无返回值。
    当进程收到信号对应的宏值为signum那么将会调用handler函数,就像QT中的connection。

以上为初级函数,无法发送信号的同时携带信息,高级函数为:
高级接收信号:
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    signum:信号值
    struct sigaction {
                   void     (*sa_handler)(int);
                   void     (*sa_sigaction)(int, siginfo_t *, void *);//由于有void*参数,可以携带复杂的数据
                   sigset_t   sa_mask;                                  //工作于信号捕捉函数执行期间屏蔽sa_mask对应的信号
                   int        sa_flags;                                  //用于设定可接收到信号外的信息
                   void     (*sa_restorer)(void);
     };
    oldact:指向的对象用来保存原来对相应信号的处理,可指定oldact为NULL(基本都让它为NULL)
    基本用法就是设定结构体,重点设置(*sa_sigaction)(int, siginfo_t *, void *)和sa_flags = SA_SIGINFO;
高级发送信号:
int sigqueue(pid_t pid, int sig, const union sigval value):
    pid:进程号
    union sigval value:
        typedef union sigval
                   { 
                        int sival_int; 
                        void *sival_ptr; 
        }sigval_t; 
        
[一些常识]:
    1.atoi函数用于将ascall对应的字符数字转换为int数字。
    2.对信号的处理有忽略捕捉和默认动作,默认动作值系统内核自动配备的handler函数,
    比如ctrl+c终止程序就是一种默认动作,它可以被更改吗,但是有些信号不可以更改默认动作也没办法忽略。

    
4.线程:


关于线程的api总共分三大类:
    线程: 创建 退出 等待
    互斥锁: 创建 销毁 上锁 解锁
    条件: 创建 销毁 广播 触发 等待
从线程开始:
线程创建函数:
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg)
    *restrict tidp:一个pthread_t类型的指针,一般定义一个 pthread_t thread 传入 &thread即可。
    const pthread_attr_t *restrict attr: 线程属性,设为NULL就行。
    void *(*start_rtn)(void *):函数指针,对应函数形式必须为:
        void *handler(void *param){}
    void *restrict arg:从名字上就知道是一个参数,会对应到函数里的param。
线程退出函数:
int pthread_exit(void *rval_ptr):
    void *rval_ptr:给&thread即可。
线程等待函数:
int pthread_join(pthread_t thread, void **rval_ptr):
    pthread_t thread:要等待的线程thread,调用该函数的线程会等待对应线程结束后在继续执行否则阻塞。
    void **rval_ptr:用原文的话说是一个指向指向退出码的指针的指针,总之它最终是退出码。
互斥锁:
创建及销毁互斥锁:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr):
    pthread_mutex_t *restrict mutex:写法有点怪,总之就是 pthread_mutex_t mutex 后传入&mutex就行。
    const pthread_mutexattr_t *restrict attr:NULL
int pthread_mutex_destroy(pthread_mutex_t mutex);
    pthread_mutex_t mutex:&mutex。
互斥锁的上锁和解锁:
互斥锁上锁函数:
int pthread_mutex_lock(pthread_mutex_t mutex):
    pthread_mutex_t mutex:&mutex。
互斥锁解锁函数:
int pthread_mutex_unlock(pthread_mutex_t mutex):
    pthread_mutex_t mutex:&mutex。
条件:
创建及销毁条件变量
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr):
    pthread_cond_t *restrict cond:pthread_cond_t cound后传入&cound。
    const pthread_condattr_t *restrict attr: NULL。
int pthread_cond_destroy(pthread_cond_t cond);
    pthread_cond_t cond:&cound。
条件等待:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
    pthread_cond_t *restrict cond:&cound
    pthread_mutex_t *restrict mutex: &mutex
    说明:该函数会阻塞直到coud的值为真。
条件触发:
int pthread_cond_signal(pthread_cond_t *cond):
    pthread_cond_t *cond:&cound
    说明:使得cond为真,会让等待函数不再阻塞。
int pthread_cond_broadcast(pthread_cond_t cond):
    而pthread_cond_broadcast函数将唤醒等待该条件的所有进程。
    
 

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值