C Programming Language
Contents
function
编译
Blog
C99标准
gcc src.c -std=c99 -o src
运行
gdb
gcc fileclient.c -g -o client
gdb client
ll
gcc fileclient.c -g -o client
gdb client
gcc fileclient.c -g -o client
gdb client
gcc fileclient.c -g -o client
gdb client
cd ../..
ll
cd socketfile/
ll
cd iclient/
ll
rm -rf color.txt rove.txt test.xlsx client
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
flags = fcntl(sockfd,F_GETFL,0);
fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK);
gdb 使用方法
Thread Process
Blog
Thread Process
Basic
同一进程中的多条进程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。
但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register)、自己的线程本地存储(thread-local starage).
一个进程可以有很多线程,每个线程执行不同的任务。
进程的组成:程序+数据集合+PCB(程序控制块)
PCB:包含进程的描述信息和控制信息,是进程存在的唯一标志
进程的基本特征:动态性+并发性+独立性+结构性
- 动态性:进程是程序的一次执行过程,是临时的,有生命周期的,是动态产生,动态消亡的;
- 并发性:任何进程都可以同其他进程一起并发执行;
- 独立性:进程是系统进行资源分配和调度的一个独立单位;
- 结构性:进程由程序、数据和进程控制块三部分组成。
Linux进程间通信
- 管道(pipe)及有名管道(named pipe)
- 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程的某种事件,除了用于进程间通信外,进程还可以发送信号给进程本身。
- 报文(Message)队列信息(消息队列):
- 共享内存:
- 信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段
- 套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程通信。
include
#include
// Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a
//因此在编译时要加上-lpthread选项
-lpthread
pthread_create()
pthread()用来创建线程并启动
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (start_routine)(void ), void * arg);
thread:线程指针
attr:线程属性指针,pthread_attr_t用来指定线程优先级等属性
void *:函数指针,线程要执行的代码
arg:传递给func的参数
返回值:0 成功
errorcode 错误
pthread_cancel()
一个线程可以调用pthread_cancel终止同一进程中的另一个线程
int pthread_cancel(pthread_t thread);
pthread_exit()
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
pthread_join()
线程等待
main函数执行的线程称为主线程,多线程的执行顺序由线程调度决定
等待线程结束,这个函数是一个线程阻塞函数。调用他的函数将一直等待到线程结束为止。
pthread_join(t1,NULL);
第一个参数t1:线程ID
第二个参数:用来接受线程函数的返回值
pthread_self()
获取当前线程的线程TID
-lpthread
linux下编译C代码时error:undefined reference to sem_init sem_wait解决方法之一
因为pthread并非Linux系统的默认库,编译时注意加上-pthread参数,以调用连接库
gcc -o server.out server.c -lpthread
sem_wait()
是一个原子操作,作用为从信号量的值减去一个“1”
sem_init()
sem_init()函数是Posix信号量操作中的函数
sem_t,信号量的数据类型
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem : //指向信号量对象,指向信号量结构的一个指针
pshared : //指明信号量的类型。不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享。
value : //指定信号量值的大小
pthread_t
类型变量
用于声明线程ID,线程结构,用来保存线程的相关数据,可理解为线程类型,声明一个线程对象(变量)
void *
C语言中void * 为 “不确定类型指针”,void *可以用来声明指针
sem_init
sigset_t
信号集及信号集操作函数:信号集被定义为一种数据类型,主要与信号阻塞相关函数配合使用。
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t
//信号集操作定义的相关函数
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum)
int sigdelset(sigset_t *set, int signum);
int [sigismember](https://baike.baidu.com/item/sigismember)(const sigset_t *set, int signum);
int sigaction( int sig, const struct sigaction *act,struct sigaction *oact );
头文件
#include
sigemptyset(sigset_t *set)初始化由set指定的信号集,信号集里面的所有信号被清空;
sigfillset(sigset_t *set)调用该函数后,set指向的信号集中将包含linux支持的62种信号;
sigaddset(sigset_t *set, int signum)在set指向的信号集中加入signum信号;
sigdelset(sigset_t *set, int signum)在set指向的信号集中删除signum信号;
[sigismember](https://baike.baidu.com/item/sigismember)(const sigset_t *set, int signum)判定信号signum是否在set指向的信号集中。
int sigaction( int sig, const struct sigaction *act,struct sigaction *oact )[检查](https://baike.baidu.com/item/%E6%A3%80%E6%9F%A5)、修改和指定信号相关联的信号响应。
Linux Unix select()
博客
select()函数
作用:多路检测可用套接字
返回:满足条件的套接口的数目
select()
#include
#include
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
int select(int nfds, fd_set *readset, fd_set *writeset,fd_set* exceptset, struct tim *timeout);
nfds:需要检查的文件描述字个数(即检查到fd_set的第几位),数值应该比三组fd_set中所含的最大fd值更大,一般设为三组fd_set中所含的最大fd值加1(readset, writeset, exceptset 中的最大值为5,则nfds=6,因为fd是从0开始的)
readset:用来检查可读性的一组文件描述字
writeset:用来检查可写性的一组文件描述字
exceptset:用来检查是否有异常条件出现的文件描述字
timeout:用来描述一段时间长度,如果在这个时间内需要监视的描述符没有事件发生函数返回,返回值为0,阻塞:NULL,
maxfd:需要监视的最大的文件描述字值+1
struct timeval:结构用于描述一段时间长度,如果在这个时间内,需要监视的描述字没有事件发生则返回函数,返回值为0
fd_set:是一组文件描述字(fd)的集合,它用一位来表示一个fd,对于fd_set类型通过下面四个宏来操作:
{
FD_ZERO(fd_set *fdset); //将指定的文件描述字集清空,在对文件描述字集合进行设置前,必须对其进行初始化,如如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
FD_SET(fd_set *fdset); //用于在文件描述字集合中增加一个新的文件描述符
FD_CLR(fd_set *fdset); //用于在文件描述符集合中删除一个文件描述符
FD_ISSET(int fd,fd_set *fdset) //用于测试指定的文件描述符是否在该集合中
}
STDIN_FILENO:接收键盘的输入
STDOUT_FILENO:向屏幕输出
Function(Learning) Home
inet_pton() & inet_npton()
Features:将IP地址在“点分十进制”和“二进制整数”之间转换
inet_pton();“点分十进制”到“二进制整数”
inet_nton();“二进制整数”到“点分十进制”
WINDOWS:
#include
LINUX:
#include
#include
#include
int inet_pton(int af, const char *src, void *dst){
af = AF_INET //第一个参数af是地址簇
*src /*第二个参数*src是来源地址,
af设置为AF_INET,src为指向字符型的地址(ddd.ddd.ddd.ddd格式),
函数将该地址转换为in_addr的结构体,并复制在*dst中*/
*dst //第三个参数* dst接收转换后的数据
af = AF_INET6 //第一个参数af是地址簇
*src /*为指向IPV6的地址,函数将该地址转换为in6_addr的结构体,并复制在*dst中*/
*dst //第三个参数* dst接收转换后的数据
}
inet_npton(){
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
}
atoi()
Features: ascii to integer
int atoi(const char *nptr);
htons()
Features: 主机字节顺序 to 网络字节顺序,就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。网络字节顺序采用
htons() host to network short
htonl() host to network long
ntohs() network to host short
ntohl() network to host long
memset()
结构体或数组进行清零操作的一种最快方法
//函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
void *memset(void *s, int ch, size_t n);
bzero()
//bzero()会将参数s 所指的内存区域前n 个字节,全部设为零值
extern void bzero(void *s, int n)
string function
strcmp()
String comparison
int strcmp(const char *str1, const char *str2)
strcpy()
string copy
strcat()
文件操作