系统编程学习笔记

*系统编程**

一、文件描述符

(一)open打开文件
int open(const char *pathname, int flags);
	参数:
		@pathname 路径 
        @flags 标志位
        	O_RDONLY	:表示只读
			 O_WRONLY	:表示只写
			 O_RDWR		:表示可读可写
			 O_CREAT	:表示创建
			 O_TRUNC	:表示清空
			 O_APPEND	:表示追加
			 O_NONBLOCK	:表示取消阻塞
                 
             r	:	O_RDONLY
            r+	:	O_RDWR	
            w	:	O_CREAT | O_TRUNC | O_WRONLY
            w+	:	O_RDWR | O_CREAT | O_TRUNC	
            a	:	O_APPEND | O_CREAT | O_WRONLY
            a+	:	O_APPEND | O_CREAT | O_RDWR
    retrun:
		成功:未使用最小文件描述符
            0 标准输入 stdin
			1 标准输出 stdout
			2 错误输出 stderr
        失败:-1
(二)close关闭文件
int close(int flags);
	参数:
        @flags 要关闭的文件描述符
(三)read读文件
ssize_t read(int fd, void *buf, size_t count);
	参数:
        @fd 文件描述符
		@buf 存储数据空间地址
		@count 要读的多少字节
	返回值:
		成功:读到的字符个数
		失败:-1
(四)write写文件
ssize_t write(int fd, const void *buf, size_t count);
	参数:
		@fd 文件描述符
		@buf 存储数据空间地址
		@count 要写的多少字节
	返回值:
		成功:写入的字符个数
		失败:-1
(五)lseek指针偏移
off_t lseek(int fildes, off_t offset, int whence);
	参数:
        @fildes 文件描述符
        @offser 偏移量
        @whence 相对位置
            SEEK_SET(开头)
            SEEK_CUR(当前)
            SEEK_END
	返回值:
		成功:偏移大小(文件开头)
		失败:-1

二、其他一些命令

(一)共享文件描述符

(一)dup
int dup(int oldfd);
	参数:
		@oldfd 文件描述符
	返回值:
        成功:未使用最小共享文件描述符
        失败:-1
(二)dup2
int dup2(int oldfd, int newfd);
	参数:
		@oldfd 旧文件描述符
		@newfd 新文件描述符
	返回值:
        成功:指定使用的最小文件描述符
        失败:-1
	如果指定正在使用的文件描述符,则会把使用的文件描述符关闭掉,然后在指向旧的文件描述符。

(二)执行外部命令exec

(一)execl
int execl(const char *path, const char  *arg0,  ...  /*,  (char *)0 */);
	参数:
        @path 命令路径(绝对路径)
        @arg0 命令名
        @...	命令的参数
        (char *)0 : 表示命令参数结束标记
	return:
		成功:0
		失败:-1

三、进程编程

(一)创建进程
pid_t fork(void);
	返回值:
		-1 : 失败
		0 : 子进程
		child_pid : 父进程
		
pid_t vfork(void);
		1 不可以使用return , 则会导致段错误
		2 vfork()创建子进程,可以确保子进程先运行
		3 vfork创建的内存空间是共享的
(二)进程等待
pid_t wait(int *status);
	参数:
		@status 等待子进程退出状态
			不关心子进程状态 NULL
	返回值:
		成功:返回等待进程的进程号
		失败:-1
父进程等待子进程,只能等待任意一个子进程

四、进程间的通信

(一)信号

软中断机制,并不是正确发送数据

(一)信号源:kill -l
2) SIGINT	: ctrl + c
3) SIGQUIT	: ctrl + \
6) SIGABRT	: abort
9) SIGKILL	: 杀死信号
13) SIGPIPE	:管道异常信号
14)SIGALRM	:闹钟信号 
(二)发送信号
int kill(pid_t pid, int sig);
	参数:
        @pid 进程号
        @sig 信号值
     return:
		成功:
        失败:-1
(三)捕捉信号
sighandler_t signal(int signum, sighandler_t handler);
	参数:
		@signum 捕捉信号值
		@handler 捕捉到信号执行操作
			SIG_DFL : 表示终止
			SIG_IGN : 表示忽略
			sighandler_t : 表示自定义
			typedef void (*sighandler_t)(int);
	返回值:
		失败: SIG_ERR
		成功:!SIG_ERR

(二)管道

(一)基本概念
管道:异步通知 半双工模式
匿名管道:通过管道标识来通讯
	只能实现父子进程或者兄弟进程之间通讯。
有名管道:就是通过管道文件通讯
	可以实现任意进程之间通讯

数据通讯的三种方式:

	1 单工:这根管道只能发送数据或者说只能接受数据
	2 半双工:这根管道一端只能接受数据而另一端只能发送数据
	3 全双工:这根管道一端即可以发送数据也可以接受数据
(二)匿名管道
int pipe(int filedes[2]);
	参数:
        @filedes 数组  
			filedes[0]  is for reading
			filedes[1] is for writing
	返回值:
		成功:0
		失败:-1
(三)有名管道
int mkfifo(const char *pathname, mode_t mode);
	参数:
        @pathname 文件路径
        @mode 文件权限
	返回值:
		成功:0
		失败:-1
(四)文件存在
int access(const char *pathname, int mode);
	参数:
		@pathname 路径
		@mode 模式
			R_OK: 是否有读的权限
			W_OK: 写
			X_OK: 可执行
			F_OK: 判断文件是否存在
	返回值:
		成功:0
		失败:-1

(三)消息队列(IPC)

(零)获取key
 key_t ftok(const char *pathname, int proj_id);
	参数:
        @pathname 路径
        @proj_id 用户指定的序号
	return:
		成功:key
		失败:-1
(一)创建消息队列
int msgget(key_t key, int msgflg);
	参数:
		@key 关键字
		@msgflg 标志位
        	IPC_CREAT 创建消息队列
        	IPC_EXCL 判断消息队列是否存在,与IPC_CREAT配合			使用
	return:
		成功:消息队列id
		失败:-1
(二)发送消息
int  msgsnd(int  msqid,  const void *msgp, size_t msgsz,int msgflg);
	参数:
		@msgid 消息队列id
	    @msgp 发送消息空间地址
		@msgsz 消息大小
		@msgflg 标志位 0
			IPC_NOWAIT :表示是否阻塞
	返回值:
		失败:-1
		成功:0
(三)接收信息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
	参数:
        @msgid 消息队列id
        @msgp 存储数据空间地址
        @msgsz 空间大小
        @msgtyp 数据类型
            不考虑数据类型 :0
        @msgflg 标识位 0
     return:
     	失败:-1
		成功:接受字符个数
(四)销毁消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
	参数:
	@msgid 消息队列id
	@buf 执行指令
		IPC_STAT : 表示获取消息队列属性
		IPC_SET  : 表示修改消息队列属性
		IPC_RMID : 表示销毁消息队列
		.....
	返回值:
		成功:...
		失败:-1

(四)共享内存(IPC)

(一)创建共享内存
int shmget(key_t key, size_t size, int shmflg);
	参数:
        @key 关键字
		@size 共享内存大小
		@shmflg 标志位 
			IPC_CREAT
	返回值:
		成功:返回共享内存id
		失败:-1
(二)共享内存映射
void *shmat(int shmid, const void *shmaddr, int shmflg);
	参数:
        @shmid 共享内存id
        @shmaddr 映射空间地址
            NULL : 系统自动分配一个可以操作地址空间
        @shmflg 标志位
            0 : 可读可写
	返回值:
		失败:NULL
		成功:表示系统允许操作的空间地址
(三)解除共享映射
int shmdt(const void *shmaddr);
	参数:
		@shmaddr 映射内存地址
	return:
		成功:0
		失败:-1
(四)销毁共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
	参数:
		@shmid 共享内存id
		@cmd 
    		IPC_RMID : 销毁指令
		@buf 
    return:
		成功:
        失败:-1

(五)信号量(IPC)

(一)创建信号量锁
int semget(key_t key, int nsems, int semflg);
	参数:
        @key 关键字
        @nsems 锁的个数
        @semflg 标志位
            IPC_CREAT
	返回值:
		失败:-1
		成功:表示信号量锁的id
(二)初始化信号锁
int semctl(int semid, int semnum, int cmd, ...);
	参数:
        @semid 锁的id
		@semnum 锁的索引号
			锁的索引号是从0开始,依次类推
		@cmd 对锁执行命令
            IPC_STAT : 表示锁属性
            IPC_SET	 :  表示设置锁属性
            IPC_RMID : 表示锁的销毁
            SETVAL	 : 表示某一把锁
			锁的状态必须是打开状态
		@... 对命令补充
	返回值:
		成功:0
		失败:-1
(三)加锁和解锁
int  semop(int  semid,  struct  sembuf  *sops,  unsigned nsops);
	参数:
        @semid 信号量锁id
        @sops 信号量锁信息结构体
            unsigned short sem_num; 锁的索引号 	
            short sem_op;  正数:解锁,负数:加锁
            short sem_flg;  锁的标志:0互斥锁
        @nsops 锁的个数
	返回值:
		成功:0
		失败:-1

五、线程

(一)基本概念
线程:
	一段可执行程序,并且在内存中运行
	识别线程的唯一标识是线程号
属性:
	进程独享内存空间,而线程是共享内存空间
关系:
	一个程序,至少包括一个进程,而一个进程至少包括一个线程。
	进程是资源管理的最小单位
	线程是执行流的最小单位
	进程包括线程,而不是线程包括进程

区别?
	1 线程的执行效率比进程要高,因为进程独享内存空间,而线程是共享内存空间,所以进程之间切换需要时间上开销,而线程切换不需要时间上开销。
	2 进程在保护模式下异常退出,另一个进程不受影响。但是同一进程的线程出现异常,则导致整个进程的所有线程出现异常。
(二)获取线程号
pthread_t pthread_self(void);
	注意:
		1 线程号类型
			%lu 
		2 线程属于第三方库
			-l pthread
(三)创建线程
int pthread_create(pthread_t *restrict thread,
		const pthread_attr_t *restrict attr,
		void  *(*start_routine)(void*),  void  *restrict arg);
	参数:
        @restrict rhread 存储创建线程的线程号
        @restrict attr 线程属性
            一般为NULL
        @start_routine 线程执行函数
            NULL : 表示线程创建成功后不执行
        @restrict arg 线程执行函数参数
            NULL : 表示不给线程执行函数传递参数
	返回值:
		成功:0
		失败:!0
(四)线程退出
void pthread_exit(void *value_ptr); 
	参数:
		线程返回地址
			NULL
(五)线程等待
int pthread_join(pthread_t thread, void **value_ptr);
	参数:
        @thread 等待线程的线程号
        @value_ptr 等待线程返回值
            NULL : 不接受返回值
	返回值:
(六)线程互斥锁
动态锁:
1 初始化锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
	参数:
		@nutex 锁变量
		@restrict attr 锁属性
			NULL

2 锁销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
	参数:
		@mutex 锁变量
		
3 设置加锁和解锁
表示加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
表示解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
尝试 加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);

静态锁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
	不用初始化和销毁锁,直接加锁解锁
(七)线程清理
注册函数
void pthread_cleanup_push(void  (*routine)(void*),void *arg);		
	参数:
        @routine 函数指针
		@arg 清理函数参数

清理执行函数
void pthread_cleanup_pop(int execute);
	参数:
        @execute 是否执行清理函数
            !0 执行清理函数
            0 不执行清理函数
	注意:
		1 代码执行跟代码所在的位置有关
		2 注册函数和清理函数要一一对应
		3 注册函数和清理函数是相反的 先进后出
  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值