原文地址:
http://www.cnblogs.com/hebaichuanyeah/p/3349061.html
感觉linux环境下C编程主要是一堆库函数的调用。
一.关于linux进程控制
关于进程的创建。
linux中fork()和vfork()函数可以创建一个子进程。
其中vfork()创建的子进程与父进程共享数据,仅子进程先与父进程运行。
代码:fork()创建子进程
#include "unistd.h"
#include "stdio.h"
main()
{
pid_t result;
result = fork();
if(result == -1)
printf("error");
else if(result == 0)
printf("\n\nresult:%d\nin child process\npid:%d\n\n",result,getpid());
else
printf("result:%d\nin father process\npid:%d",result,getpid());
}
代码:由于vfork()创建的子进程与父进程共享数据
#include "stdio.h"
#include "unistd.h"
main()
{
pid_t pid;
int count = 0;
pid = vfork();
count++;
if(pid == -1)
printf("error");
else if(pid == 0)
printf("in child process count is:%d\n",count);
else
printf("in father process count is:%d\n",count);
}
关于exec函数族
exec函数族,可以在一个进程中启动另一个程序,当该进程不能为系统和用过贡献时,可以调用exec族函数执行另一个程序。
代码:execl调用编译后的helloworld.c文件
#include "stdio.h"
#include "unistd.h"
main()
{
if(execl("/home/he/program/ctest/helloworld",NULL)<0)
printf("error\n");
}
关于wait()与waitpid()函数。
wait()与waitpid可以阻塞父进程。
pid_t wait(int *status)
waitpid原型
代码:waitpid使用
#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "sys/wait.h"
main()
{
pid_t result;
int pr;
result = fork();
if(result == -1)
printf("error\n");
else if(result == 0)
{
sleep(5);
printf("\n\nresult:%d\nin child process\npid:%d\n\n",result,getpid());
}
else
{
while(!(pr=waitpid(result,NULL,WNOHANG)))
{
sleep(1);
printf("the child process not exit\n");
}
printf("result:%d\nin father process\npid:%d\n\n",result,getpid());
}
}
关于linux守护进程
守护进程是linux后台服务进程,该进程独立于终端,周期性执行某种任务。
代码:编写守护进程
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<syslog.h>
#define MAXFILE 65535
int main()
{
pid_t pc,sid;
int i,fd,len;
char *buf="This is a Dameon\n";
len =strlen(buf);
pc=fork();
if(pc<0)
{
printf("error fork\n");
exit(1);
}else if(pc>0)
exit(0);
openlog("demo_update",LOG_PID, LOG_DAEMON);
if((sid=setsid())<0)
{
syslog(LOG_ERR, "%s\n", "setsid");
exit(1);
}
if((sid=chdir("/"))<0)
{
syslog(LOG_ERR, "%s\n", "chdir");
exit(1);
}
umask(0);
for(i=0;i<MAXFILE;i++)
close(i);
while(1)
{
if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND, 0600))<0)
{
syslog(LOG_ERR, "open");
exit(1);
}
write(fd, buf, len+1);
close(fd);
sleep(10);
}
closelog();
exit(0);
}
该进程会10s周期向目标文件写入数据。
二.进程件的通讯
关于管道通讯
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int pipe_fd[2],New_process_result;
char send_data[] = "This a message from father process";
char receive_data[100];
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
}
else
printf("pipe create success\n");
if((New_process_result=fork()) == -1)
{
printf("Fork error\n");
}
else if(New_process_result == 0)//子进程
{
sleep(1);
read(pipe_fd[0],receive_data,100);
printf("%s",receive_data);
putchar('\n');
}
else//父进程
{
write(pipe_fd[1],send_data,strlen(send_data));
sleep(2);
}
}
在子进程中,打印父进程写入的数据。
关于FIFO有名管道
pipe管道只能用于父子进程通讯。
FIFO可以用于任意两个进程间的通讯。
fifo_write.c 写数据文件
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"
main(int argc,char** argv)
{
int fd;
char w_buf[100];
char exitflag[] = "exit";
int nwrite;
fd = open(FIFO_SERVER,O_RDWR|O_NONBLOCK,0);
if(fd==-1)
{
perror("open error");
exit(1);
}
else
printf("open success\n");
while(1)
{
scanf("%s",&w_buf[0]);
if((nwrite=write(fd,w_buf,100))==-1)
{
if(errno==EAGAIN)
printf("The FIFO has not been read yet.Please try later\n");
}
else
printf("write %s to the FIFO\n",w_buf);
if(!(strcmp(w_buf,exitflag)))
exit(1);
}
}
fifo_read读数据文件
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"
main(int argc,char** argv)
{
char buf_r[100];
char exitflag[] = "exit";
int fd;
int nread;
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("cannot create fifoserver\n");
printf("Preparing for reading bytes...\n");
memset(buf_r,0,sizeof(buf_r));
fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd==-1)
{
perror("open");
exit(1);
}
while(1)
{
memset(buf_r,0,sizeof(buf_r));
read(fd,buf_r,100);
if(buf_r[0] == '\0')
;
else if(!strcmp(buf_r,exitflag))
exit(1);
else
printf("read %s from FIFO\n",buf_r);
}
pause();
unlink(FIFO);
}
在两个不同的终端中运行结果:
exit退出程序。
关于信号
代码:signal键入信号(ctrl C)信号处理函数:sigint_handler
#include "stdio.h"
#include "signal.h"
#include "stdlib.h"
void sigint_handler(int sign_num)
{
if(sign_num == SIGINT)
printf("\n\"SIGINT\" singal\n");
}
int main()
{
signal(SIGINT,sigint_handler);
pause();
}
代码sigaction函数
#include "stdio.h"
#include "signal.h"
#include "stdlib.h"
void sigint_handler(int sign_num)
{
if(sign_num == SIGINT)
printf("\n\"SIGINT\" singal\n");
}
int main()
{
struct sigaction my_signal;
my_signal.sa_handler = sigint_handler;
sigemptyset(&my_signal.sa_mask);
my_signal.sa_flags = 0;
sigaction(SIGINT,&my_signal,0);
pause();
}
代码:父进程发生信号杀死子进程
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
if((pid=fork())<0)
{
perror("fork");
exit(1);
}
if(pid == 0) //子进程
{
while(1)
{
printf("child process runing\n");
sleep(1);
}
}
else //父进程
{
int count;
for(count=0;count<5;count++)
{
sleep(1);
printf("father process runing\n");
}
if((count = kill(pid,SIGKILL)) == 0)
{
printf("\n\nfather process kill:%d\n",pid);
}
}
}
关于信号量
同uc/os-II信号量用于对共享资源的标记
sem_com.h文件 信号量操作
#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/shm.h"
#include "sys/sem.h"
extern int init_sem( int sem_id, int init_value );
extern int del_sem( int sem_id );
extern int sem_p( int sem_id );
extern int sem_v( int sem_id );
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
//struct seminfo *_buf;
};
sem_com.c文件
#include "sem_com.h"
int init_sem( int sem_id, int init_value )
{
union semun sem_union;
sem_union.val = init_value;
if ( semctl(sem_id, 0, SETVAL, sem_union) == -1 )
{
perror( "initialize semaphore" );
return(-1);
}
return(0);
}
int del_sem( int sem_id )
{
union semun sem_union;
if ( semctl(sem_id, 0,IPC_RMID, sem_union) == -1 )
{
perror( "Delete semaphore" );
return(-1);
}
return(0);
}
int sem_p( int sem_id )
{
struct sembuf sem_b;
sem_b.sem_num = 0; /* id */
sem_b.sem_op = -1; /* P operation */
sem_b.sem_flg = SEM_UNDO;
if ( semop(sem_id, &sem_b, 1) == -1 )
{
perror( "P operation" );
return(-1);
}
return 0;
}
int sem_v( int sem_id )
{
struct sembuf sem_b;
sem_b.sem_num = 0; /* id */
sem_b.sem_op = 1; /* V operation */
sem_b.sem_flg = SEM_UNDO;
if ( semop(sem_id, &sem_b, 1) == -1 )
{
perror( "V operation" );
return(-1);
}
return 0;
}
主函数main.c文件
#include "sem_com.h"
int main()
{
pid_t result;
int sem_id;
sem_id = semget(1,1,0666|IPC_CREAT);
init_sem(sem_id, 0);
sem_v(sem_id);
result = fork();
if(result == -1)
printf("error");
else if(result == 0) //子进程
{
sem_p(sem_id);
printf("child process get sem\n");
sem_v(sem_id);
}
else //父进程
{
sem_p(sem_id);
printf("father process get sem\n");
sleep(3);
printf("father process used sem\n");
sem_v(sem_id);
sleep(1);
}
exit(0);
}
由于父进程先运行子进程无法获取信号量,在父进程sleep中,子进程依然无法运行。
关于共享内存
由shmget函数创建共享内存shmat函数映射共享内存地址。
代码:由父进程写入共享内存,子进程读取。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int shmid,process_ret;
char *shmadd;
if((shmid=shmget(IPC_PRIVATE, 1024, 0666))<0)
{
perror("shmget");
exit(1);
}
if((process_ret = fork()) == -1)
printf("process creat error\n");
else if(process_ret == 0)//子进程
{
sleep(2);
printf("in child process\n");
if((shmadd=shmat(shmid,0,0)) == (void*)(-1))
{
perror("shmat");
exit(1);
}
//shmadd = "acc";不能这么干,shmadd地址改变了。
shmadd[0] = 'A';
printf("In child process:%s\n",shmadd);
if((shmdt(shmadd))<0)
{
perror("shmdt");
exit(1);
}
}
else //父进程
{
char share_message[] = " this is share context from father process";
int count;
printf("in father process\n");
if((shmadd=shmat(shmid,0,0)) == (void *)(-1))
{
perror("shmat");
exit(1);
}
for(count=0;share_message[count]!='\0';count++)
shmadd[count] = share_message[count];
if((shmdt(shmadd))<0)
{
perror("shmdt");
exit(1);
}
sleep(10);
}
}
消息队列
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <sys/msg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <string.h>
8
9 struct message
10 {
11 long msg_type;
12 char msg_text[512];
13 };
14
15 int main()
16 {
17 int qid;
18 key_t key;
19 int len;
20 struct message msg;
21 char a[100];
22
23 if((key=ftok(".",'a'))==-1)
24 {
25 perror("ftok");
26 exit(1);
27 }
28 if((qid=msgget(key,IPC_CREAT|0666))==-1) //创建消息列对
29 {
30 perror("msgget");
31 exit(1);
32 }
33 printf("Please send a message:");
34
35 scanf("%s",&msg.msg_text[0]);
36
37 msg.msg_type = getpid();
38
39 len = strlen(msg.msg_text);
40
41 if((msgsnd(qid,&msg,len,0))<0) //发送消息
42 {
43 perror("message posted");
44 exit(1);
45 }
46
47 if(msgrcv(qid,&msg,BUFSZ,0,0)<0) //接受消息
48 {
49 perror("msgrcv");
50 exit(1);
51 }
52
53 printf("message is:%s\n",&msg.msg_text[0]); //删除消息
54
55 if((msgctl(qid,IPC_RMID,NULL))<0)
56 {
57 perror("msgctl");
58 exit(1);
59 }
60 exit(0);
61 }
三.关于线程
linux的线程,类似于uC/os-II中的“任务”。
进程的创建
#include "stdio.h"
#include "pthread.h"
#include "stdlib.h"
void thread_one(void)
{
int i;
for(i=0;i<10;i++)
printf("thread one is runing\n");
}
void thread_two(void)
{
int i;
sleep(1);
for(i=0;i<10;i++)
printf("thread two is runing\n");
}
main()
{
pthread_t thread_one_id,thread_two_id;
int resurt;
if((resurt = pthread_create(&thread_one_id, NULL, (void *)thread_one, NULL))== -1)
{
printf("thread one creat error\n");
exit(1);
}
if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
{
printf("thread two creat error\n");
exit(1);
}
pthread_join(thread_one_id, NULL);
pthread_join(thread_two_id, NULL);
}
进程有多个属性。(优先级,分离,绑定……)
可通过相应的函数设置创建相应属性进程。
创建优先级为11,时间片轮转调度,绑定,分离属性的进程
thread_one_priority = 11;
pthread_attr_init(&thread_one_attr);
pthread_attr_setinheritsched(&thread_one_attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&thread_one_attr, SCHED_RR);
pthread_attr_setschedparam(&thread_one_attr, (struct sched_param *)&thread_one_priority);
pthread_attr_setscope(&thread_one_attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate(&thread_one_attr,PTHREAD_CREATE_DETACHED);
if((resurt = pthread_create(&thread_one_id, &thread_one_attr, (void *)thread_one, NULL)))
{
printf("thread one creat error\n");
exit(1);
}
互斥锁使用
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void thread_one(void)
{
printf("thread_one attempt lock\n");
pthread_mutex_lock(&mutex);
printf("thead_one lock success\n");
sleep(2);
printf("thread_one is runing\n");
printf("thread_one unlock\n");
pthread_mutex_unlock(&mutex);
}
void thread_two(void)
{
sleep(1);
printf("thread_two attempt lock\n");
pthread_mutex_lock(&mutex);
printf("thead_two lock success\n");
printf("thread_two is runing\n");
printf("thread_two unlock\n");
pthread_mutex_unlock(&mutex);
}
main()
{
pthread_t thread_one_id,thread_two_id;
int resurt;
pthread_mutex_init(&mutex,NULL);
if((resurt = pthread_create(&thread_one_id, NULL, (void *)thread_one, NULL))== -1)
{
printf("thread one creat error\n");
exit(1);
}
if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
{
printf("thread two creat error\n");
exit(1);
}
pthread_join(thread_one_id, NULL);
pthread_join(thread_two_id, NULL);
}
由于使用互斥锁,进程2等待进程1解锁,才能运行。