一、基础知识
源程序编译
/***hello.c***/
int main() {printf("hello,world. "); return 0;}
gcc -o hello hello.c
-o生成可执行文件
-c只输出目标代码
-g可调试
makefile编写
####makefile1####
main: main.o t1.o t2.o
gcc -o $@ $^
main.o: main.c t1.h t2.h
gcc -c $<
t1.o: t1.c t1.h
gcc -c $<
t2.o: t2.c t2.h
gcc -c $<
$@##目标文件
$^##所有依赖文件
$<##第一个依赖文件
####makefile2####
main: main.o t1.o t2.o
gcc -o $@ $^
..c.o
gcc -c $<
##自动推导
程序库的连接
-lm数学库
-lpthread线程库
系统的缺省库路径:/lib, /usr/lib, /usr/local/lib
否则要指定连接路径:-L/home/ming/mylibs -lming 这样就会到相应目录下连接libming.so|libming.a
调试
参考gdb入门
帮助
man write ###write命令的帮助
man 2 write ###系统调用函数的帮助
man 3 write ###C库函数的帮助
二、进程
进程概念
进程是程序的执行过程,即一个开始执行但没有结束的程序的实例。每个进程可以有多个子进程...
为了区分不同的进程,系统给每个进程分配了唯一的id以示区别
进程的状态:新建、运行、阻塞、就绪、完成
个人理解:linux下的多线程根本上都是多个子进程,分别拥有自己的进程id,但没有自己的进程名,与之对应的父进程的程序名。
查看进程命令:ps, 如:ps -ef, ps -aux
进程的标志
#include <unistd.h>
pid_t getpid();//获得进程id
pid_t getppid();//获得父进程id
进程是为程序服务的,程序是为用户服务的。系统为了找到进程的用户名,为进程和用户建立了联系。这个用户成为进程的所有者,相应的每个用户也有一个用户id。用户隶属不同的组,每个组也有自己的id。
#include<unistd.h><sys/types.h>
uid_t getuid();//获得进程所有者用户id
uid_t geteuid();//获得进程的有效用户id
gid_t getgid();//获得组id
gid_t getegid();//获得有效组id
进程的创建
#include<unistd.h>
pid_t fork();//创建进程
对于父进程fork()返回子进程的id,对于fork子进程返回0,创建进程失败返回-1。一旦子进程被创建,就与父进程一起从fork处继续执行,相互竞争系统的资源。如果希望子进程执行,而父进程阻塞直到子进程完成,这是可以调用wait()或waitpid()函数。
父进程创建子进程后,子进程一般要调用不同的程序。为了调用系统程序,可以使用如下的exec族的函数:
#include<unistd.h>
int execl(char*path,char*arg,...);
int execlp(char*file,char*arg,...);
int execle(char*path,char*arg,...);
int execv(char*path,char*argv[]);
int execvp(char*file,char*argv[]);
/********forktest.c**********/
#include<unistd.h><sys/types.h><sys/wait.h><stdio.h><errno.h><math.h>
void main()
{
pid_t child;
int status;
if((child = fork()) == -1) exit(1);
else if(child == 0)
{
int i;
printf("i am the child: %ld ", getpid());
for(i=0; i<1000000; i++) sin(i);
exit(5);
}
while(((child=wait(&status))==-1)&&(errno==EINTR));
if(child == -1)printf("wait error: %s ", strerror(errno));
else if(!status);
else {...}
}
守护进程
/****checkmail.c****/
#include<unistd.h><sys/types.h><sys/stat.h><stdio.h><errno.h><fcntl.h><signal.h>
#define MAIL "/var/spool/mail/ming"
#define SLEEP_TIME 10
void main()
{
pid_t child;
if((child=fork())==-1)exit(1);
else if(child>0)while(1);
if(kill(getppid(),SIGTERM)==-1)exit(1);
int mailfd;
while(1)
{
mailfd=open(MAIL,O_RDONLY);
close(mailfd);
sleep(SLEEP_TIME);
}
}
三、文件操作
文件读写
/*****filerw.h****/
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sting.h>
#define BUF_SIZE 1024
int main(int argc, char** argv)
{
int from_fd, to_fd;
int bytes_read, bytes_write;
char buf[BUF_SIZE];
char* ptr;
if(argc != 3) {
fprintf(stderr, "Usage: %s fromfile tofile
a", argv[0]);
exit(1);
}
if((from_fd = open(argv[1], O_RDONLY)) == -1) exit(1);
if((to_fd = open(argv[2], O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)) == -1) exit(1);
while(bytes_read = read(from_fd, buf, BUF_SIZE))
{
if((bytes_read = -1) && (errno != EINTR)) break;
else if(bytes_read > 0) {
ptr = buf;
while(bytes_write = write(to_fd, ptr, bytes_read))
{
if((bytes_write == -1) && (errno != EINTR)) break;
else if(bytes_write == bytes_read) break;
else if(bytes_write > 0) {
ptr += bytes_write;
bytes_read -= bytes_write;
}
if(bytes_write == -1) break;
}
}
}
close(from_fd);
close(to_fd);
return 0;
}
目录操作
/******dir_opt.c********/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <time.h>
static int get_file_size_time(const char* filename)
{
struct stat statbuf;
if(stat(filename, &statbuf) == -1) return -1;
if(S_ISDIR(statbuf.st_mode)) return 1;
if(S_ISREG(statbuf.st_mode)) {
printf("%s size: %ldbytes modified at %s
", filename, statbuf.st_size, ctime(&statbuf.st_mtime));
}
return 0;
}
int main(int argc, char** argv)
{
DIR* dirp;
struct dirent* direntp;
int stats;
if(argc != 2) {
printf("Usage: %s filename
a", argv[0]);
exit(1);
}
if(((stats = get_file_size_time(argv[1])) == 0) || (stats == -1)) exit(1);
if((dirp = opendir(argv[1])) == NULL) {
exit(1);
}
while((direntp = readdir(dirp)) != NULL);
closedir(dirp);
return 0;
}
管道文件
/********pipe.c*********/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER 255
int main(int argc, char** argv)
{
char buffer[BUFFER+1];
int fd[2];
if(argc != 2) {
fprintf(stderr, "Usage: %s string
a", argv[0]);
exit(1);
}
if(pipe(fd) != 0) exit(1);
if(fork() == 0) {
close(fd[0]);
printf("child[%d] write to pipe.
", getpid());
snprintf(buffer, BUFFER, "%s", argv[1]);
write(fd[1], buffer, strlen(buffer));
printf("child[%d] quit.
", getpid());
exit(0);
}
else {
close(fd[1]);
printf("parent[%d] read from pipe
", getpid());
memset(buffer, 0, BUFFER+1);
read(fd[0], buffer, BUFFER);
printf("parent[%d] read: %s
", getpid(), buffer);
exit(1);
}
return 0;
}
四、时间
时间表示
#include <sys/time.h>
time_t time(time_t* tloc);//返回1970年至今的秒数
char* ctime(const time_t* clock);//返回类似"Fri Nov 7 13:40:58 2014"字符串
gettimeofday();//获得一天内的时间
计时器
todo......
五、信号处理
todo
六、消息管理
todo
七、线程操作
子进程是通过拷贝父进程的地址空间来执行的,线程是通过共享程序代码来执行的。
-lpthread连接线程库
#include <pthread.h>
int pthread_create(pthread_t* thread, pthread_attr_t* attr, void*(*start_routine)(void*), void* arg);
void pthread_exit(void* retval);
int pthread_join(pthread* thread, void** thread_return);
简易生产者-消费者实现:
#include <stdio.h>
#include <pthread.h>
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* producer(void* argv) {
while (1) {
pthread_mutex_lock(&mutex);
count++;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
sleep(1);
}
return NULL;
}
void* consumer(void* argv) {
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("count = %d
", count);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t t1=0, t2=0;
pthread_create(&t1, NULL, producer, NULL);
pthread_create(&t2, NULL, consumer, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
生产者-消费者实例2
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
int count = 0;
sem_t sem;
void* producer(void* argv) {
while (1) {
count++;
sem_post(&sem);
sleep(1);
}
return NULL;
}
void* consumer(void* argv) {
while (1) {
sem_wait(&sem);
printf("count=%d
", count);
}
return NULL;
}
int main() {
sem_init(&sem, 0, 0);
pthread_t t1 = 0;
pthread_t t2 = 0;
pthread_create(&t1, NULL, producer, NULL);
pthread_create(&t2, NULL, consumer, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
sem_destroy(&sem);
return 0;
}
八、网络编程
tcp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 80
int main() {
int listenfd, connfd;
int n, i;
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
char buf[MAXLINE];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8888);
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
listen(listenfd, 10);
while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddr_len);
n = read(connfd, buf, MAXLINE);
for (i = 0; i < n; i++) {
buf[i] = toupper(buf[i]);
}
write(connfd, buf, n);
close(connfd);
}
return 0;
}
tcp_client.c
int main() {
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n;
char* str = "hello,world.";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(8888);
connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
write(sockfd, str, strlen(str));
n = read(sockfd, buf, MAXLINE);
write(STDOUT_FILENO, buf, n);
close(sockfd);
return 0;
}
udp_server.c
#define MAXLINE 80
int main() {
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int sockfd;
char buf[MAXLINE];
int i,n;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8888);
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
while (1) {
cliaddr_len = sizeof(cliaddr);
n = recvfrom(sockfd, buf, MAXLINE, 0, (struct sockaddr*)&cliaddr, &cliaddr_len);
for (i = 0; i < n; i++) {
buf[i] = toupper(buf[i]);
}
n = sendto(sockfd, buf, n, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
}
return 0;
}
udp_client.c
#define MAXLINE 80
int main() {
struct sockaddr_in servaddr;
int sockfd, n;
char buf[MAXLINE];
socklen_t servaddr_len;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(8888);
while (fgets(buf, MAXLINE, stdin) != NULL) {
n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, 0);
write(STDOUT_FILENO, buf, n);
}
return 0;
}