一、dup、dup2
int dup(int oldfd);
int dup2(int oldfd,int newfd);
dup函数创建一个新的文件描述符,该新文件描述符和原文件描述符指向相同的文件、管道或者网络连接,并且dup返回的新文件描述符是取系统当前可用的最小整数值,dup2和dup类似,不过它返回的是第一个不小于新文件描述符的整数值,dup和dup2调用失败时都返回-1并设置errno
二、stdin、stdout、stderr和STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO的区别和联系
stdin类型为 FILE*
STDIN_FILENO类型为 int三、浅谈printf、fprintf、sprintf的使用和区别
fprintf可以把数据写入文件中,借助的是第一个参数(FILE*的指针)
fprintf比printf也只多了一个FILE*指针,后面两个参数和printf一样写就行
sprintf的作用:
官方点: sprintf的作用是将一个格式化的字符串输出到一个目的字符串中
参数里的buffer指针就是指向目的字符串的
简单点:把数据输出到一个字符串四、Linux access函数讲解
#include<unistd.h>
int access(const char* pathname, int mode);
参数介绍:
pathname 是文件的路径名+文件名
mode:指定access的作用,取值如下
F_OK 值为0,判断文件是否存在
X_OK 值为1,判断对文件是可执行权限
W_OK 值为2,判断对文件是否有写权限
R_OK 值为4,判断对文件是否有读权限
注:后三种可以使用或“|”的方式,一起使用,如W_OK|R_OK
五、C语言strlen与sizeof的区别详解
strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)。
六、进程
1、fork()创建进程、复制地址空间
子进程返回0,父进程返回子进程pid
2、sleep()进程挂起
3、wait()、waitpid()进程收尸、等待进程
4、exit()、_exit()进程结束
5、exit库函数、_exit函数系统调用
exec族进程替换、完全替换、进程号不变
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
解析:
1>exec函数族一共有6个成员
2>exec函数族都是exec开头
不带p :根据路径来加载程序
带p :根据(执行目录)文件名来加载程序 默认路径:/usr/bin 和 /bin 用来保存命令
带l :根据列举来加载程序 --->直接提供参数
带v :根据数组来加载程序 --->将参数塞入到数组中,并以数组作为参数给函数
带e :根据环境变量加载程序后传递某些数据
exec失败返回-1,并设置错误码七、进程通信
1、有名管道
mkfifo("./fifo",0777)创建有名管道
2、无名管道
只适用于父子进程
char pp[1];
pipe(pp)创建无名管道
3、信号
唯一异步通信,类似中断。
raise()发信号给自身进程
alarm()闹钟
kill()发信号
pause()等待信号
signal()注册信号
4、消息队列
ipcs -q
ipcrm -q <id>
int msgget(key_t key, int msgflg); //创建或获取消息队列
//参数1 ---- 消息队列的key:
方法一:IPC_PRIVATE ---- 系统自动分配key
方法二:调用函数ftok ---返回key值
key_t ftok(const char *pathname, int proj_id);
//参数1 ---- 字符串,表示工程路径
//参数2 ---- 工程编号
//返回值----成功:key,失败:-1
//参数2 ----- 消息队列的权限,一般为: IPC_CREAT | 0666
IPC_CREAT 如果key不存在,则创建(类似open函数的O_CREAT)
IPC_EXCL 如果key存在,则返回失败(类似open函数的O_EXCL)
IPC_NOWAIT 如果需要等待,则直接返回错误
//返回值 ---- 成功:消息队列的ID,失败:-1 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//参数1 ----- 消息队列ID
//参数2 ----- 结构体struct msgbuf 类型的指针 ,,该结构体需要自定义
struct msgbuf {
long mtype; /* message type, must be > 0 */ 消息类型
char mtext[1]; /* message data */ 消息正文
};
//参数3 ----- 消息正文的实际字符长度
//参数4 ----- 发送方式:
IPC_NOWAIT 消息没有发送完成函数也会立即返回。
0:直到发送完成函数才返回
//返回值 ------ 成功:0,失败:-1 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//参数1 ----- 消息队列ID
//参数2 ----- 结构体struct msgbuf 类型的指针 ,,该结构体需要自定义
struct msgbuf {
long mtype; /* message type, must be > 0 */ 消息类型
char mtext[1]; /* message data */ 消息正文
};
//参数3 ----- 消息正文的长度
//参数4 ----- 要接收的消息的类型msgtyp
msgtyp = 0,表示接收消息队列中第一个消息(按顺序接收所有类型消息)
msgtyp > 0,表示接收指定类型的消息
msgtyp < 0,表示接收消息类型不大于msgtyp的绝对值的最小消息
//参数5 ----- 发送方式:
IPC_NOWAIT 消息没有发送完成函数也会立即返回。
0:直到发送完成函数才返回
//返回值 ------ 成功:接收的消息的字节数,失败:-1 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//参数1 ---- 消息队列ID
//参数2 ---- 命令:cmd
IPC_STAT ---- 获取消息队列属性
IPC_SET ---- 设置消息队列属性
IPC_RMID ---- 删除消息队列
//参数2 ---- 如果mcd不是IPC_RMID,则需要该参数,struct msqid_ds结构体指针
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
//返回值 ---成功:0,失败:-15、共享内存
ipcs -m
int shmget(key_t key, size_t size, int shmflg);
//参数1 ---- 共享内存的key:
方法一:IPC_PRIVATE ---- 系统自动分配key
方法二:调用函数ftok ---返回key值
key_t ftok(const char *pathname, int proj_id);
//参数1 ---- 字符串,表示工程路径
//参数2 ---- 工程编号
//返回值----成功:key,失败:-1
//参数2 ----- 共享内存的大小
//参数3 ----- 共享内存的权限,一般为: IPC_CREAT | 0666
//返回值 ---- 成功:共享内存的ID,失败:-1 void *shmat(int shmid, const void *shmaddr, int shmflg);
//参数1 ---- 共享内存id
//参数2 ---- 指定映射虚拟空间地址,但是,一般为NULL,由系统自动映射
//参数3 ---- 共享内存使用权限
SHM_RDONLY:共享内存只读
默认0:共享内存可读写
//返回值 -----成功:映射的虚拟空间地址,失败:-1 int shmdt(const void *shmaddr);
//参数 ------映射的进程的虚拟地址,也就是shmat()返回的地址
//返回值 ----- 成功:0,失败:-1 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//参数1 ---- 共享内存ID
//参数2 ---- 命令:cmd
IPC_STAT ---- 获取共享内存属性
IPC_SET ---- 设置共享内存属性
IPC_RMID ---- 删除共享内存
//参数2 ---- 如果mcd不是IPC_RMID,则需要该参数,struct msqid_ds结构体指针
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
}; //返回值 ---成功:0,失败:-1
6、信号量
信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制
信号灯种类:
posix有名信号灯
posix基于内存的信号灯(无名信号灯)
System V信号灯(IPC对象)
从使用上分为二值信号灯和计数信号灯两种:1》 二值信号灯 -----表示资源是否可用
值为0或1。与互斥锁类似,资源可用时值为1,不可用时值为0。
2》计数信号灯 -----表示资源数量
值在0到n之间。用来统计资源,其值代表可用资源数用信号灯实现进程的同步,需要实现两个操作
3》等待操作
等待操作也叫P操作,等待信号灯的值变为大于0,然后将其减1;
4》释放操作
释放操作也叫V操作,用来唤醒等待资源的进程或者线程
5》System V的信号灯
是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。int semget(key_t key, int nsems, int semflg);
//参数1 ---- 信号灯的key:
方法一:IPC_PRIVATE ---- 系统自动分配key
方法二:调用函数ftok ---返回key值
key_t ftok(const char *pathname, int proj_id);
//参数1 ---- 字符串,表示工程路径
//参数2 ---- 工程编号
//返回值----成功:key,失败:-1
//参数2 ----- 信号灯对象(集合)中的信号灯的个数
//参数3 ----- 信号灯的权限,一般为: IPC_CREAT | 0666
//返回值 ---- 成功:信号灯的ID,失败:-1 int semop(int semid, struct sembuf *sops, size_t nsops);
//参数1 ----- 信号灯对象的ID
//参数2 ----- 结构体struct sembuf的指针
struct sembuf {
unsigned short sem_num; /* semaphore index in array 操作的信号灯的下标 */
short sem_op; /* semaphore operation
0 : 等待,直到信号灯的值变成0
1 : 释放资源,V操作
-1 : 分配资源,P操作*/
short sem_flg; /* operation flags:0, IPC_NOWAIT, SEM_UNDO */
};
//参数3 ----要操作次数
//返回值 -----成功:0,失败:-1 int semctl(int semid, int semnum, int cmd, ...);
//参数1 ---- 信号灯对象ID
//参数2 ---- 要操作的信号灯的编号
//参数3 ---- 名称cmd:
GETVAL:获取一个信号灯的值
SETVAL:设置一个信号灯的值
IPC_RMID:从系统中删除信号灯集合
GETALL:获取所有信号灯的值
SETALL:设置所有信号灯的值
//参数4 ----- 联合体,该联合体需要自定义,如下:
union semun {
int val; /* Value for SETVAL 设置一个信号灯的值时使用 */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL 获取或设置所有信号灯的值时使用 */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};八、线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 创建线程
Compile and link with -pthread. -------//如果程序中使用上面函数,编译时,需要链接库: -lpthread
//参数1 ---- 保存线程ID的变量地址
//参数2 ---- 线程属性,一般为NULL,默认属性
//参数3 -----线程执行的函数(线程函数),格式必须为:
void* 线程函数名称(void * arg)
{
//线程执行代码
........
}
//参数4 ---- 传给线程的参数
//返回值 ----成功:0,失败:非0值 void pthread_exit(void *retval); 结束线程 //Compile and link with -pthread.
//参数 -----线程返回的数据地址,该数据必须在线程返回后空间没有释放 #include <pthread.h>
int pthread_join(pthread_t thread, void **retval); 线程收尸 // Compile and link with -pthread.
//参数1 ----线程ID
//参数2 ---- 保存线程返回值的指针的地址
//返回值 --- 成功:0,失败:非0 int pthread_cancel(pthread_t thread); //Compile and link with -pthread
//参数 ---- 线程ID
//返回值 ---- 成功:0,失败:非01》概念
在创建线程时,默认为结合属性,当线程结束时,它不会自动释放资源,需要主线程调用pthread_join()来回收资源
在创建线程时,也可以将线程的属性改为分离属性,此时,当线性结束时,会自动释放资源,此时不需要再调用pthread_join()
设置线程的分离属性有两种方式:
2》方式一:直接给pthread_create传递线程属性变量,设置分离属性
int pthread_attr_init(pthread_attr_t *attr); //初始化线程属性变量
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
//参数1 ---- 属性变量地址
//参数2 ---- 要设置的属性:
PTHREAD_CREATE_DETACHED ---分离
PTHREAD_CREATE_JOINABLE ---结合3》使用线程函数
int pthread_detach(pthread_t thread);
//参数 ---- 线程ID
//返回值 ---- 成功:0,失败:非0
pthread_t pthread_self(void);
//返回调用该函数的线程的ID
消息队列接收串口数据 消息队列key
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章