linux下c编程入门笔记

一、基础知识

源程序编译

/***hello.c***/

int main() {printf("hello,world.\n"); return 0;}

gcc -o hello hello.c

-o生成可执行文件

-c只输出目标代码

-g可调试

makefile编写

####makefile1####

main: main.o t1.o t2.o

  gcc -o [email protected] $^

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 $<

[email protected]##目标文件

$^##所有依赖文件

$<##第一个依赖文件

####makefile2####

main: main.o t1.o t2.o

  gcc -o [email protected] $^

..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\n", 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\n", 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 \n\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 \t modified at %s \n", 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 \n\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\n\a", argv[0]);
        exit(1);
    }
    if(pipe(fd) != 0) exit(1);
    if(fork() == 0) {
        close(fd[0]);
        printf("child[%d] write to pipe. \n", getpid());
        snprintf(buffer, BUFFER, "%s", argv[1]);
        write(fd[1], buffer, strlen(buffer));
        printf("child[%d] quit. \n", getpid());
        exit(0);
    }
    else {
        close(fd[1]);
        printf("parent[%d] read from pipe \n", getpid());
        memset(buffer, 0, BUFFER+1);
        read(fd[0], buffer, BUFFER);
        printf("parent[%d] read: %s\n", 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);

八、网络编程

todo

时间: 2024-11-06 09:32:42

linux下c编程入门笔记的相关文章

Linux下C编程入门

1.首先,以Ubuntu 64-bit操作系统下为例 图中的sudo su表示的是快速进入到root管理员下.这里的密码默认的是安装后的Ubunto操作系统中自定义的用户名的密码,此处以用户toto,密码:123456为例 2.在/demo目录下创建以下三个文件(看截图): 注意:其中add.c的内容如下(通过vi编辑器编辑add.c): 其中的add.h(用于声明同级目录下的add.c文件中编写的函数).截图如下: 3.关于自定义add.h函数的引用,在main.c中的写法如下: 4.编译ad

Linux Shell脚本编程学习笔记和实战

http://www.1987.name/141.html shell基础 终端打印.算术运算.常用变量 Linux下搜索指定目录下特定字符串并高亮显示匹配关键词 从键盘或文件中获取标准输入 [read命令] 文件的描述符和重定向 数组.关联数组和别名使用 函数的定义.执行.传参和递归函数 条件测试操作与流程控制语句 获取时间日期格式和延时 [date.sleep命令] 内部字段分隔符IFS和脚本的调试DEBUG 显示.读取或拼接文件内容 [cat命令] 文件查找与打印文件列表 [find命令]

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一

Unix/Linux环境C编程入门教程(5) Red Hat Enterprise Linux(RHEL)环境搭建

Unix/Linux版本众多,我们推荐Unix/Linux初学者选用几款典型的Unix/Linux操作系统进行学习. Red Hat Enterprise Linux是Red Hat公司的Linux发行版,面向商业市场,包括大型机.红帽公司从Red Hat Enterprise Linux 5开始对企业版LINUX的每个版本提供10年的支持[1].而Red Hat Enterprise Linux常简作RHEL. 1. 启动Vmware,如果没有安装的话,请看前面VMware安装的视频 2.选中

根据《linux兵书》目录 在kali上操作 第8章 Linux下的编程

第8章  浑水摸鱼:Linux下的编程 175 8.1  Linux下常用的开发工具 176 8.1.1  GCC 176 8.1.2  CVS 176 8.1.3  Perl 176 8.1.4  Linux上的Delphi--Kylix 177 8.2  Linux下的Vi文本编辑器 177 8.2.1  Vi编辑器介绍 178 8.2.2  启动Vi编辑器 179 8.2.3  显示Vi中的行号 180 8.2.4  光标移动操作 181 8.2.5  屏幕命令 182 8.2.6  文本

Linux下Socket编程

http://blog.chinaunix.net/uid-20733992-id-3450058.html 原文地址:Linux下Socket编程 作者:yulianliu1218 Linux下Socket编程 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. Socket接口设计者最先是将接口放在Unix操作系统里面

Linux下Socket编程的端口问题( Bind error: Address already in use )

Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误: Bind error: Address already in use 虽然用Ctrl+C强制结束了进程,但错误依然存在,用netstat -an |grep 5120和ps aux |grep 5120都还能看到刚才用Ctrl+C“强制结束”了的进程,端口还是使用中,只好每次用kill结束进程,

Linux下Shell编程

Linux的shell编程 1.什么是shell? 当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shell(外壳)的程序. shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动.挂起.停止甚至是编写一些程序.一般的Linux系统都将bash作为默认的shell. 2.几种流行的shell 目前流行的shell有ash.bash.ksh.csh.zsh等,可以用下面的命令来查看she

linux 下 poll 编程

poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪.如果有就返回就绪文件描述符的个数将.poll 函数如下: #include <poll.h> int poll(struct pollfd *fdarray, unsigned long nfds, int timeout) 第一个参数指向结构数组第一个元素的指针,每个数组都是一个 pollfd 结构iouyonghu制定额是某个给定描述符的条件. struct pollfd { int fd; short eve