C指针原理(45)-LINUX应用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C指针原理(45)-LINUX应用相关的知识,希望对你有一定的参考价值。
一、在linux平台下,每个线程可有专用数据:
#include <pthread.h>
#include <stdio.h>
struct mydata{
? ? ? ?int x;
? ? ? ?char c[4];
};
pthread_t pthreada,pthreadb;
pthread_key_t datakey;//每个进程创建一次,不同的线程,同样名字的键指向不同的地方
void *cleanup_mydata(void *dataptr){//删除键时调用的
? ? free((struct mydata*)dataptr);
}
void anum1(){
? ? int rc;
? ? struct ?mydata *mdata=(struct mydata*)malloc(sizeof(struct mydata));
? ? mdata->x=1;
? ? mdata->c[0]=‘a‘;
? ? mdata->c[1]=‘ ‘;?
? ? rc=pthread_setspecific(datakey,(void*)mdata);//设置键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存?
? ? sleep(1);
? ? struct ?mydata *mmdata=(struct mydata*)pthread_getspecific(datakey);//取出键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存?
? ? printf("-%d-%s
",mmdata->x,mmdata->c);?
? ? fflush(stdout);?
}
void bnum2(){
? ? int rc;
? ? struct ?mydata *mdata=(struct mydata*)malloc(sizeof(struct mydata));
? ? mdata->x=2;
? ? mdata->c[0]=‘b‘;
? ? mdata->c[1]=‘ ‘;?
? ? rc=pthread_setspecific(datakey,(void*)mdata);//设置键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存?
? ? sleep(1);
? ? struct ?mydata *mmdata=(struct mydata*)pthread_getspecific(datakey);//取出键指向的值,注意这个mdata为值的内存,必须使用指针的方式指向内存?
? ? printf("-%d-%s
",mmdata->x,mmdata->c);
? ? fflush(stdout);?
}
int main(void){
? ? int rc;
? ? rc=pthread_key_create(&datakey,cleanup_mydata);//为键删除时的清理函数
? ? pthread_create(&pthreada,NULL,anum1,NULL);?
? ? pthread_create(&pthreadb,NULL,bnum2,NULL); ?
? ? sleep(3);
? ? pthread_join(pthreada,NULL); ??
? ? pthread_join(pthreadb,NULL); ?
? ? rc=pthread_key_delete(datakey); //仅删除键,但不删除值指向的内存,线程终止调用用户自定义的删除函数,本例中为cleanup_mydata
}
二、摸拟shell
通过execlp函数来实现 ,execlp函数用于执行文件
其参数与说明为:
#include <process.h>
int execlp( const char file,
const char arg0,
const char arg1,
…
const char argn,
NULL );
file,
const char arg0,
const char arg1,
…
const char * argn,
NULL );
Arguments:
file
Used to construct a pathname that identifies the new process image file. If the?fileargument contains a slash character, the?file?argument is used as the pathname for the file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable?PATH.
arg0, …,?argn
Pointers to?NULL-terminated character strings. These strings constitute the argument list available to the new process image. Terminate the list terminated with a?NULL?pointer. The?arg0?argument must point to a filename that‘s associated with the process.
waitpid()
wait for process termination?
Function
?SYNOPSIS?DESCRIPTION?PARAMETERS?RETURN VALUES?CONFORMANCE?MULTITHREAD SAFETY LEVEL?PORTING ISSUES?AVAILABILITY?SEE ALSO?
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t?pid, int *stat_loc, int?options);
DESCRIPTION
The?waitpid()?function lets the calling process obtain status information about one of its child processes. If status information is available for two or more child processes, the order in which their status is reported is unspecified. If more than one thread is suspended in?waitpid()?awaiting termination of the same process, exactly one thread returns the process status at the time of the target child process termination. The other threads return -1, with?errno?set to?ECHILD.
If the calling process sets?SIGCHLD?to?SIG_IGN, and the process has no unwaited for children that were transformed into zombie processes, the calling thread blocks until all of the children of the process terminate, at which time?waitpid()?returns -1 with?errno?set to?ECHILD.
If the parent process terminates without waiting for all of its child processes to terminate, the remaining child processes are assigned a new parent process ID corresponding to a system-level process.
PARAMETERS
pid?
Specifies a set of child processes for which the status is requested:
If?pid?is equal to -1, status is requested for any child process. In this respect,?waitpid()?is equivalent to?wait().
If?pid?is greater than 0, it specifies the process ID of a single child process for which status is requested.
If?pid?is 0, status is requested for any child process whose process group ID is equal to that of the calling process. This setting is not currently supported.
If?pid?is less than -1, status is requested for any child process whose process group ID is equal to the absolute value of?pid. This setting is not currently supported.
stat_loc?
Specifies the location to which the child process‘ exit status is stored. If?NULL?is passed, no exit status is returned. Otherwise, the following macros defined in?<sys/wait.h>?can be used to evaluate the returned status:
WIFEXITED(s)?
Evaluates to a non-zero value if status was returned for a child process that exited normally.
WEXITSTATUS(s)?
If the value of?WIFEXITED(s)?is non-zero, this macro evaluates to the low-order 8 bits of the status argument that the child process passed to?exit()?or?_exit(), or to the value that the child process returned from?main().
WIFSIGNALED(s)?
Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught.
WTERMSIG(s)?
If the value of?WIFSIGNALED(s)?is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.
WIFCORED(s)?
Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught, and whose default action is to dump core.
WCOREDUMP(s)?
Evaluates to a non-zero value if status was returned for a child process that terminated due to receipt of a signal that was not caught, and whose default action is to dump core.
WCORESIG(s)?
If the value of?WIFCORED(s)?is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.
WIFSTOPPED(s)?
Evaluates to a non-zero value if status was returned for a child process that is currently stopped.
WSTOPSIG(s)?
If the value of?WIFSTOPPED(s)?is non-zero, this macro evaluates to the number of the signal that caused the child process to stop.
options?
Is the bitwise inclusive-OR of zero or more of the following flags, defined in?<sys/wait.h>:
WNOHANG?
The?waitpid()?function does not suspend execution of the calling thread if status is not immediately available for one of the child processes specified by?pid.
WUNTRACED?
The status of any child processes specified by?pid?that are stopped, and whose status has not yet been reported since they stopped, is also reported to the requesting thread. This value is currently not supported, and is ignored.
RETURN VALUES
If?waitpid()?was invoked with?WNOHANG?set in?options, and there are children specified by?pid?for which status is not available,?waitpid()?returns 0. If?WNOHANG?was not set,waitpid()?returns the process ID of a child when the status of that child is available. Otherwise, it returns -1 and sets?errno?to one of the following values:
ECHILD?
The process or process group specified by?pid?does not exist or is not a child of the calling process.
EFAULT?
stat_loc?is not a writable address.
EINTR?
The function was interrupted by a signal. The value of the location pointed to by?stat_loc?is undefined.
EINVAL?
The?options?argument is not valid.
ENOSYS?
pid?specifies a process group (0 or less than -1), which is not currently supported.
程序如下:
#include <stdio.h>
#include <sys/wait.h>
#define MAXLINE 100
//execlp模拟SHELL
int main(void){
? ?int pid;
? ?int jg,status,len;
? ?char buf[MAXLINE];
? ?printf("
##myhaspl~~");//自定义的shell提示符
? ?while(fgets(buf,MAXLINE,stdin)!=NULL){//读入一行
? ? ? ? len=strlen(buf)-1;
? ? ? ? if (buf[len]==‘
‘){ ? ? ? ?//去除换行符,execlp只接受以NULL结尾
? ? ? ? ? ? buf[len]=0; ? ? ? ? ? ?
? ? ? ? }
? ? ? ? pid=fork();
? ? ? ? if (pid<0){
? ? ? ? ? ?printf("fork error!
");
? ? ? ? }
? ? ? ? else if (pid==0){//子进程
? ? ? ? ? ?printf("
"); ? ? ? ?
? ? ? ? ? ?if (buf[0]==‘Q‘&&strlen(buf)==1){//键入Q表示退出shell ? ? ? ? ?
? ? ? ? ? ? ? ?exit(200);?
? ? ? ? ? ?}
? ? ? ? ? ?jg=execlp(buf,buf,(char *)0);
? ? ? ? ? ?if (jg==-1){//错误
? ? ? ? ? ? ? printf("不能执行:%s
",buf); ? ?
? ? ? ? ? ? ? exit(127); ? ? ? ? ?
? ? ? ? ? ?} ? ? ? ? ? ? ?
? ? ? ? ? ? ? exit(0); ? ? ??
? ? ? ? }
? ? ? ? if ((jg==waitpid(pid,&status,0))<0){//父进程
? ? ? ? ? ? printf("waitpid error
");
? ? ? ? }
? ? ? ? if (WEXITSTATUS(status)==200) {//WEXITSTATUS计算返回值
? ? ? ? ? ? ? ? printf("退出....
"); ?
? ? ? ? ? ? ? ? break; ? ? ? ? ?
? ? ? ? }
? ? ? ? printf("
##myhaspl~~");//自定义的shell提示符
? ?}
exit(0);
}
执行:
[email protected]:~/private/mytest$ gcc -o test21 test21.c
test21.c: In function ‘main’:
test21.c:15: warning: incompatible implicit declaration of built-in function ‘strlen’
test21.c:26: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:28: warning: incompatible implicit declaration of built-in function ‘execlp’
test21.c:31: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:33: warning: incompatible implicit declaration of built-in function ‘exit’
test21.c:44: warning: incompatible implicit declaration of built-in function ‘exit’
[email protected]:~/private/mytest$ ./test21
##myhaspl~~ls
1 ? ? pvmtest ? test20 ? testbswap ?testmul.s ? ?x
ex.txt ? ? test ? ? ?test20.c ? ?testbswap.s ?testmutex ? ?x.c
gmon.out ? ? test12.s ?test21 ? test.c ?testmutex.c ?xx
hello ? ? test13 ? ?test21.c ? ?test.c~ ?testpopen ? ?xx.c
hello.c ? ? ?test13.c ?test2.c ? testmes ?testpopen.c ?xx.txt
hello.o ? ? ?test15 ? ?test6 ? testmes.c ?testpvm1.c ? xxx.txt
hello.s ? ? ?test15.c ?test66 ? testmesrecv ?testpvm2.c ? xxxx.txt
main ? ? test19 ? ?test66.s ? ?testmesrecv.c ?testpx ? ? ? xy
main.c ? ? test19.c ?test6.c ? testmessnd ?testpx1
main.c~ ? ? ?test1.c ? testasmc ? ?testmessnd.c ? testpx1.s
myhello.txt ?test2 ? ? testasmc.c ?testmul ?testpx.s
##myhaspl~~xx
不能执行:xx
##myhaspl~~Q
退出....
[email protected]:/mnt-system/lx/test$?gcc -D_REENTRANT -lpthread -o testcondout testcondout.c
[email protected]:/mnt-system/lx/test$?./testcondout
please input an integer:(<=1000)26
time out
time out
1/1 finished,push 1.0000000000
1/2 finished,push 0.5000000000
1/3 finished,push 0.3333333333
1/4 finished,push 0.2500000000
1/5 finished,push 0.2000000000
time out
1/6 finished,push 0.1666666667
1/7 finished,push 0.1428571429
1/8 finished,push 0.1250000000
1/9 finished,push 0.1111111111
1/10 finished,push 0.1000000000
time out
1/11 finished,push 0.0909090909
1/12 finished,push 0.0833333333
1/13 finished,push 0.0769230769
1/14 finished,push 0.0714285714
1/15 finished,push 0.0666666667
1/1:1.0000000000 added result 1.0000000000
1/2:0.5000000000 added result 1.5000000000
1/3:0.3333333333 added result 1.8333333333
1/4:0.2500000000 added result 2.0833333333
1/5:0.2000000000 added result 2.2833333333
1/6:0.1666666667 added result 2.4500000000
1/7:0.1428571429 added result 2.5928571429
1/8:0.1250000000 added result 2.7178571429
1/9:0.1111111111 added result 2.8289682540
1/10:0.1000000000 added result 2.9289682540
1/11:0.0909090909 added result 3.0198773449
1/12:0.0833333333 added result 3.1032106782
1/13:0.0769230769 added result 3.1801337551
1/14:0.0714285714 added result 3.2515623266
1/15:0.0666666667 added result 3.3182289932
1/1:1.0000000000 computed result 1.0000000000
1/2:0.5000000000 computed result 0.5000000000
1/3:0.3333333333 computed result 0.8333333333
1/4:0.2500000000 computed result 0.5833333333
1/5:0.2000000000 computed result 0.7833333333
1/6:0.1666666667 computed result 0.6166666667
1/7:0.1428571429 computed result 0.7595238095
1/8:0.1250000000 computed result 0.6345238095
1/9:0.1111111111 computed result 0.7456349206
1/10:0.1000000000 computed result 0.6456349206
1/11:0.0909090909 computed result 0.7365440115
1/12:0.0833333333 computed result 0.6532106782
1/13:0.0769230769 computed result 0.7301337551
1/14:0.0714285714 computed result 0.6587051837
1/15:0.0666666667 computed result 0.7253718504
===============compute finish!=========== result:0.7253718504
1/16 finished,push 0.0625000000
1/17 finished,push 0.0588235294
1/18 finished,push 0.0555555556
1/19 finished,push 0.0526315789
1/20 finished,push 0.0500000000
1/16:0.0625000000 added result 3.3807289932
1/17:0.0588235294 added result 3.4395525226
1/18:0.0555555556 added result 3.4951080782
1/19:0.0526315789 added result 3.5477396571
1/20:0.0500000000 added result 3.5977396571
1/21 finished,push 0.0476190476
1/22 finished,push 0.0454545455
1/23 finished,push 0.0434782609
1/24 finished,push 0.0416666667
1/25 finished,push 0.0400000000
time out
1/16:0.0625000000 computed result 0.6628718504
1/17:0.0588235294 computed result 0.7216953798
1/18:0.0555555556 computed result 0.6661398242
1/19:0.0526315789 computed result 0.7187714032
1/20:0.0500000000 computed result 0.6687714032
1/21:0.0476190476 computed result 0.7163904508
1/22:0.0454545455 computed result 0.6709359053
1/23:0.0434782609 computed result 0.7144141662
1/24:0.0416666667 computed result 0.6727474995
1/25:0.0400000000 computed result 0.7127474995
===============compute finish!=========== result:0.7127474995
1/21:0.0476190476 added result 3.6453587048
1/22:0.0454545455 added result 3.6908132502
1/23:0.0434782609 added result 3.7342915111
1/24:0.0416666667 added result 3.7759581778
1/25:0.0400000000 added result 3.8159581778
1/26 finished,push 0.0384615385
time out
time out
1/26:0.0384615385 computed result 0.6742859611
===============compute finish!=========== result:0.6742859611
1/26:0.0384615385 added result 3.8544197162
================add finish!============ result:3.8544197162
2个线程完成累加和累加减运算(其中一个采用超时等待条件信号,另一个采用等待条件信号),n个线程完成计算每个符点数
? ```
?#include <pthread.h> ?
? ?#include <bits/pthreadtypes.h> ?
? ?#include <stdio.h> ?
? ?#include <stdlib.h> ?
? ?#include <errno.h>?
? ?#define MAXS 1000 ??
? ?#define MAXTDS 5 //线程池大小
? ??
? ? ?
? double myjg[MAXS+1];//计算结果存放位置 ?
? int max; ?
? pthread_mutex_t eventlock; ? //互斥锁
? pthread_cond_t myevent; ? //条件变量
? pthread_t threads[MAXTDS+2]; ? //线程池,完成1/n计算
? int isend=0;
? int done; ? ?
? ??
?void mycomp(void x){//计算1/i的结果,计算结果放在一个数组中。 ?
? ?int i=0;
? ?int rc;
? ?while (1){?
? pthread_mutex_lock(&eventlock); ?
? if (isend){
? ? ? ? ? ? ?pthread_mutex_unlock(&eventlock);?
? ? ? ? ? ? ?break; ? ? ? ? ? ?
? } ?
? i=myjg[0];//myjg[0]存放着线程已经计算到的i。 ??
? if (i<max){
? ? ? i++;
? ? ? myjg[0]=i; ? ??
? } ?
? ? ? ? ?if (i==max){//最后一个数
? ? ? ? ? ? ?myjg[i]=(1/(double)i);
? ? ? ? ? ? ? isend=1;
? ? ? ? ? ?printf("1/%d finished,push %.10f
",i,myjg[i]);?
? ? ? ? ? ? ? fflush(stdout);
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);?
? ? ? ? ? ? ? sleep(3);
? ? ? ? ? ? ? rc=pthread_cond_signal(&myevent);//广播信号,多个任务不被阻塞,多个任务竞争互斥锁的所有权。也可以使用pthread_cond_signal(&event);发送信号,这样只有一个线程不被阻塞,其它线程都被阻塞。
? ? ? ? ? ? ? if (rc){
? ? ? ? ? ? ? ? ? perror("pthread_cond_broadcast");
? ? ? ? ? ? ? ? ? fflush(stdout);
? ? ? ? ? ? ? } ?
? ? ? ? ? ? ? sleep(2); ?
? ? ? ? ? ? ? break; ? ??
? ? ? ? ?}
? ??
? ? ?//开始计算
? ? ?myjg[i]=(1/(double)i); ?
? ? ?printf("1/%d finished,push %.10f
",i,myjg[i]);?
? ? ?fflush(stdout);
? ? ?pthread_mutex_unlock(&eventlock); ??
? ? ?if (!(i%MAXTDS)){
? ? ? ? sleep(3);?
? ? ? ? pthread_cond_broadcast(&myevent);//广播信号,多个任务不被阻塞,多个任务竞争互斥锁的所有权。也可以使用pthread_cond_signal(&event);发送信号,这样只有一个线程不被阻塞,其它线程都被阻塞。 ? ?
? ? ? ? sleep(3);?
? ? ?}
? }?
? pthread_exit(NULL);
} ?
? ??
?void myprint1(void xx){//读取数组,将计算结果累加,最终完成1/1+1/2+1/3+......+1/n的计算,使用超时等待 ?
? ?int maxi; ?
? ?int curj=1; ?
? ?double jg=0;?
? ?int rc;?
? ?struct timeval now;//使用微秒
? ?struct timespec timeout; ?//使用纳秒
? ? ??
? ?while(curj<=max) ?
? ? ?{ ?
? ? ? //取当前时间
? ? ? // myhaspl?
? ? ? ? ?gettimeofday(&now);
? ? ? //准备时间间隔
? ? ? ? timeout.tv_sec=now.tv_sec+1;
? ? ? ? timeout.tv_nsec=now.tv_usec*1000;
? ? ? ? ?maxi=0;
? ? ? ??
? ? ? ? ?pthread_mutex_lock(&eventlock);//用于条件变量的互斥,条件变量就是一个用来发送事件发生信号的信号量
? ? ? ? ?rc=pthread_cond_timedwait(&myevent,&eventlock,&timeout);//在等待条件变量myevent的发生,超时就返回,不再等待。条件变量必须与一个互斥锁eventlock相关联,条件变量不提供锁定,必须有一个互斥锁eventlock配合。
? ? ? ? //互斥锁eventlock在调用wait前应锁定,然后在wait期间,互斥量eventlock被解锁。挂起线程执行,直到条件变量myevent收到信号 ? ? ? ? ? ??
? ? ? ? ?if (rc==0){ ?// myhaspl
? ? ? ? ? ? ? maxi=myjg[0];?
? ? ? ? ? ? ? fflush(stdout);?
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);
? ? ? ? ? ? ? for (;curj<=maxi;curj++)
? ? ? ? ? ? ? { ? ?// myhaspl
? ? ? ? ? ? ? ? ? ?jg+=myjg[curj]; ?
? ? ? ? ? ? ? ? ? ?printf("1/%d:%.10f added result %.10f
",curj,myjg[curj],jg); ? ??
? ? ? ? ? ? ? ? ? ?fflush(stdout); ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? } ??
? ? ? ? ?}?
? ? ? ? ?else if (rc==ETIMEDOUT){//TIMEOUT
? ? ? ? ? ? ? printf("time out
");
? ? ? ? ? ? ? fflush(stdout);?
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);?
? ? ? ? ? ? ? continue; ? ? ? ? ? ?
? ? ? ? ?}?
? ? ? ? ?else ?{ ?// myhaspl
? ? ? ? ? ? ? perror("pthread_cond_wait");
? ? ? ? ? ? ? fflush(stdout);?
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);?
? ? ? ? ? ? ? continue; ? ? ? ? ? ? ?
? ? ? ? ?}
? ? } ?
? ? printf("================add finish!============ result:%.10f
",jg);//输出累加结果。 ?
? ? fflush(stdout);
? ? pthread_exit(NULL);
} ?
? ??
void myprint2(void xx){//读取数组,将计算结果完成1/1+1/2-1/3+1/4-1/5......的计算 ?
? ?int maxi=0; ?
? ?int curi=1; ?
? ?double jg=0;?
? ?int fh=1;
? ?int rc;?
? ?while(curi<=max) ?
? ? ?{ ?
? ? ? ? ?maxi=0;
? ? ? ? ?sleep(2);?
? ? ? ? ?pthread_mutex_lock(&eventlock);//用于条件变量的互斥,条件变量就是一个用来发送事件发生信号的信号量
? ? ? ? ?rc=pthread_cond_wait(&myevent,&eventlock);//在等待条件变量myevent的发生。条件变量必须与一个互斥锁eventlock相关联,条件变量不提供锁定,必须有一个互斥锁eventlock配合。
? ? ? ? //互斥锁eventlock在调用wait前应锁定,然后在wait期间,互斥量eventlock被解锁。挂起线程执行,直到条件变量myevent收到信号 ?
? // myhaspl
? ? ? ? ?if (rc==0){
? ? ? ? ? ? ? maxi=myjg[0];?
? ? ? ? ? ? ? fflush(stdout);?
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);
? ? ? ? ? ? ? while (curi<=maxi){ ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? jg+=fh*myjg[curi]; ?
? ? ? ? ? ? ? ? ? ? printf("***1/%d:%.10f computed result %.10f
",curi,myjg[curi],jg); ?
? ? ? ? ? ? ? ? ? ? fflush(stdout); ? ? ??
? ? ? ? ? ? ? ? ? ? fh=-fh;
? ? ? ? ? ? ? ? ? ? curi++;
? ? ? ? ? ? ?} ? ? ? ? ? ? ? ??
? ? ? ? ? ? ?printf("===============compute finish!=========== result:%.10f
",jg);//输出累加结果?
? ? ? ? ? ? ?fflush(stdout); ? ? ? ? ? ? ?
? ? ? ? ?}?
? ? ? ? ?else{//error
? ? ? ? ? ? ? perror("pthread_cond_wait");
? ? ? ? ? ? ? fflush(stdout);?
? ? ? ? ? ? ? pthread_mutex_unlock(&eventlock);?
? ? ? ? ? ? ? continue; ? ? ? ? ? ?
? ? ? ? ?} ?
? ?} ? ? ?
? ? pthread_exit(NULL);
?} ?
? ?
? ?int main(){ ?
? ?//计算1+1/2+1/3+......和1+1/2-1/3+1/4-1/5...... ?
? ? ?pthread_mutex_init(&eventlock,NULL);
? ? ?pthread_cond_init(&myevent,NULL); ? ? ? ??
? ? ?int i =0;
? ? ?
? ? ?printf("please input an integer:(<=%d)",MAXS); ?
? ? ?while (scanf("%d",&max),max>MAXS){//n的最大值 ?
? ? ? ? printf("please input an integer:(<=%d)",MAXS); ?
? ? ?}; ?
? ? ?//myhaspl
? ? ?myjg[0]=0;
??
? ? ?pthread_create(&(threads[i]),NULL,myprint1,(void )&i);
? ? ?sleep(1);?
? ? ?i++; ? ? ?
? ? ?pthread_create(&(threads[i]),NULL,myprint2,(void )&i); ?
? ? ?sleep(1); ?
? ? ?i++;?
? ? ?for (;i<=MAXTDS;i++){ ?
? ? ? ? ?pthread_create(&(threads[i]),NULL,mycomp,(void )&i); ?
? ? ? ? ?sleep(1); ? ? ? ?
? ? } ??
? ? sleep(MAXTDS2*(i/10+1)); ?//wait......
? ? pthread_mutex_destroy(&eventlock); ? ?
? ? return(0); ?
?} ??
? ? ?
一、端口
1、0-1023:预留端口,超级用户使用
2、1024-49151:已经注册的端口号
3、49152-65535:可自由使用的端口或动态端口
二、套接字类型
1、SOCK_STREAM(字节流套接字):面向连接,可靠的全双工字节流。对于AF_INET来说,建立TCP连接
2、SOCK_DGRAM(数据报套接字):不保证数据正确分发,不保证发送数据的训序。对于AF_INET来说,建立UDP连接
3、SOCK_RAW(原始套接字)
三、建立套接字
int fd;
fd=socket(AF_INET,SOCK_STREAM,0);//除使用SOCK_RAW外,最后一个protocol被设置为0,AF_INET为套接口
?四、应用?
1.server
[email protected]:~/private/mytest$ ./testtcps
server wait....
............................
server read :myhaspl
?
server send :hello
.....
server read :myhaspl
?
server send :hello
2.client
[email protected]:~/private/mytest$ ./testtcpc
client send....
client send :myhaspl
client read :hello
[email protected]:~/private/mytest$ ./testtcpc
client send....
client send :myhaspl
client read :hello
[email protected]:~/private/mytest$?
3.source
1)server
C代码 ?
#include <stdio.h> ?
#include <errno.h> ?
#include <sys/types.h> ?
#include <sys/socket.h> ?
#include <netinet/in.h> ?
//myhaspl ?
ssize_t readn(int fd,void ptr,size_t maxcn){//读取n个字符,maxc为读取的数目 ?
? ? size_t noreadcn,readcn; ?
? ? char buf=ptr; ?
??
? ? ??
? ? ??
? ? noreadcn=maxcn; ?
? ? while(noreadcn>0){ ?
? ? ? ?if ( (readcn=read(fd,buf,noreadcn))<0){//读数据 ?
? ? ??
? ? ? ? ? if (errno==EINTR) {//数据读取前,操作被信号中断 ?
? ? ? ? ? ? ?perror("中断错误"); ?
? ? ? ? ? ? ?readcn=0; ? ? ? ? ? ??
? ? ? ? ? } ?
? ? ? ? ? else {return -1;}//无法修复错误,返回读取失败 ?
? ? ? ?} ?
? ? ? ?else if(readcn==0) break;//EOF ?
? ? ? ? ?
? ? ? ? ?
? ? ? ?noreadcn-=readcn;//读取成功,但是如果读取的字符数小于maxc,则继续读,因为可能数据还会继续通过网络送过来 ? ? ?
? ? ? ?buf+=readcn; ? ?
? ? ? ?if (buf==0) break;//如果读到字符串结尾标志则退出,必须有这句,否则会死循环 ?
? ? ? ?} ? ?
??
??
? ? ? ?
? ? return (maxcn-noreadcn); ?
} ?
??
ssize_t ?writen(int fd,void ptr,size_t maxcn){//写入n个字符 ?
? ? size_t nowritecn,writecn; ?
? ? char buf=ptr; ?
??
? ? ??
? ? nowritecn=maxcn; ?
? ? while(nowritecn>0){ ?
? ? ? ?if((writecn=write(fd,buf,nowritecn))<=0){//写数据 ?
? ? ? ? ?
? ? ? ? ? if (errno==EINTR) {//数据写前,操作被信号中断 ?
? ? ? ? ? ? ?perror("中断错误"); ?
? ? ? ? ? ? ?writecn=0; ? ? ? ? ? ? ??
? ? ? ? ? } ?
? ? ? ? ? else {return -1;}//无法修复错误,返回读取失败 ?
? ? ? ?} ?
??
? ? ? ??
? ? ? ?nowritecn-=writecn; ?
? ? ? ?buf+=writecn; ? ?
??
? ? ? ?} ??
??
? ? ? ?return (maxcn-nowritecn); ?
} ?
??
int main(void){ ?
? ? int fd; ?
? ? int addresslen; ?
? ? struct sockaddr_in address;//地址信息结构 ?
? ? int pid; ?
? ? int rc; ?
? ? fd_set fdset; ?
? ? ??
??
??
? ? ? ? ? ? ? ? ? ??
? ? //建立socket ?
? ? fd=socket(AF_INET,SOCK_STREAM,0);//fd为socket ?
? ? if (fd==-1){//错误,类型从errno获得 ?
? ? ? ? perror("error");//perror先输出参数,后跟":"加空格,然后是errno值对应的错误信息(不是错误代码),最后是一个换行符。 ? ? ? ? ?
? ? } ?
? ? ??
? ? //bind 到socket fd ? ? ?
? ? address.sin_family=AF_INET;//IPV4协议,AF_INET6是IPV6 ?
? ? address.sin_addr.s_addr=htonl(INADDR_ANY);//l表示32位,htonl能保证在不同CPU的相同字节序 ?
? ? address.sin_port=htons(1253);//端口号,s表示16位 ?
? ? addresslen=sizeof(address); ?
? ? ??
??
? ? bind(fd,(struct sockaddr )&address,addresslen);//bind ?
? ? ??
? ? ? ? ? ?//建立socket队列,指定最大可接受连接数 ?
? ? ? ? ? ?rc=listen(fd,32);//最多接收32个连接,开始监听 ?
? ? ? ? ? ?//int listen(int sockfd, int backlog)返回:0──成功, -1──失败 ?
? ? ? ? ? ?//内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接 ?
? ? ? ? ? ?if (rc==-1) { ?
? ? ? ? ? ? ? perror("listen error");//监听失败 ?
? ? ? ? ? ? ? exit(1); ?
? ? ? ? ? ?} ?
? ? ? ? ? ?printf("server wait....
"); ? ? ? ? ? ??
? ? ? ? ? ?while(1){ ?
??
? ? ? ? ? ? ? struct sockaddr_in clientaddress; ?
? ? ? ? ? ? ? int address_len; ?
? ? ? ? ? ? ? int client_sockfd; ?
? ? ? ? ? ? ? char mybuf[100]; ? ? ?
? ? ? ? ? ? ? char buf="hello
"; ? ?
? ? ? ? ? ? ? struct timeval timeout;//超时结构体 ?
? ? ? ? ? ? ? //超时为2秒 ?
? ? ? ? ? ? ? timeout.tv_sec=1; ?
? ? ? ? ? ? ? timeout.tv_usec=0; ?
? ? ? ? ? ? ? //设置fdset ?
? ? ? ? ? ? ? FD_ZERO(&fdset);//清除fdset ?
? ? ? ? ? ? ? FD_CLR(fd,&fdset);//清除fd的标志 ?
? ? ? ? ? ? ? FD_SET(fd,&fdset);//设置标志 ?
? ? ? ? ? ? ? //select ?
? ? ? ? ? ? ? if ((select(fd+1,&fdset,NULL,NULL,&timeout))<0){ ?
? ? ? ? ? ? ? ? ? perror("select error"); ?
? ? ? ? ? ? ? ? ? fflush(stdout); ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? } ?
? ? ? ? ? ? ? //等待连接,使用新的进程或线程来处理连接 ?
??
? ? ? ? ? ? ? fflush(stdout); ? ? ??
? ? ? ? ? ? ? address_len=sizeof(clientaddress); ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? if(FD_ISSET(fd,&fdset)){ ?
? ? ? ? ? ? ? ? ? //如果有连接到来 ?
? ? ? ? ? ? ? ? ?client_sockfd=accept(fd,(struct sockaddr )&clientaddress,&address_len);//client_sockfd可理解为一个文件句柄,能用read和write操作。client_address是客户端信息结构 myhaspl ?
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? //fork进程来处理每个客户的连接 ? ? ? ?
? ? ? ? ? ? ? ? ? pid=fork(); ?
? ? ? ? ? ? ? ?if (pid<0){//错误 ?
? ? ? ? ? ? ? ? ? ? printf("error:%s
",strerror(errno));//strerror将errno映射为一个错误信息串 myhaspl ?
? ? ? ? ? ? ? ? ? ? close(client_sockfd); ?
? ? ? ? ? ? ? ? ? ? exit(1); ??
? ? ? ? ? ? ? ? } ? ??
??
? ? ? ? ? ? ? ? ?if (pid==0){ //子进程处理每个客户端的数据 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ?close(fd);//子进程关闭不需要它处理的监听资源 ?
??
? ? ? ? ? ? ? ? ? ? ? //读取数据 myhaspl ?
? ? ? ? ? ? ? ? ? ? ? bzero(mybuf,100); ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ?readn(client_sockfd,(void )mybuf,100); ?
? ? ? ? ? ? ? ? ? ? ? printf("
server read :%s",mybuf); ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ?//发送数据 ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? writen(client_sockfd,(void )buf,strlen(buf)+1); ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ?printf("
server send :%s",buf); ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?close(client_sockfd); ?
? ? ? ? ? ? ? ? ? ? ? ?exit(0); ?
? ? ? ? ? ? ? ? ?} ?
? ? ? ? ? ? ? ? ? else {//父进程 ?
? ? ? ? ? ? ? ? ? ? ? ? ? close(client_sockfd);//父进程不处理客户端连接,因此关闭,但并不意味着把子进程的处理句柄关闭,因为子进程继承了父进程的client_sockfd资源 ? ? ? ? myhaspl ? ? ??
? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? }else{ ?
? ? ? ? ? ? ? ? ? printf("."); ?
? ? ? ? ? ? ? ? ? fflush(stdout); ?
? ? ? ? ? ? } ?
? ? ? ?} ?
?} ?
?2) client
C代码 ?
#include <stdio.h> ?
#include <errno.h> ?
#include <sys/types.h> ?
#include <sys/socket.h> ?
#include <netinet/in.h> ?
//myhaspl ?
ssize_t readn(int fd,void ptr,size_t maxcn){//读取n个字符,maxc为读取的数目 ?
? ? size_t noreadcn,readcn; ?
? ? char buf=ptr; ?
? ? ??
? ? ??
? ? noreadcn=maxcn; ?
? ? while(noreadcn>0){ ?
? ? ? ?if ( (readcn=read(fd,buf,noreadcn))<0){//读数据 ?
? ? ??
? ? ? ? ? if (errno==EINTR) {//数据读取前,操作被信号中断 myhaspl ?
? ? ? ? ? ? ?perror("中断错误"); ?
? ? ? ? ? ? ?readcn=0; ? ? ? ? ? ? ?
? ? ? ? ? } ?
? ? ? ? ? else {return -1;}//无法修复错误,返回读取失败 ?
? ? ? ?} ?
? ? ? ?else if(readcn==0) break;//EOF myhaspl ?
? ? ? ? ? ? ?
? ? ? ?noreadcn-=readcn;//读取成功,但是如果读取的字符数小于maxc,则继续读,因为可能数据还会继续通过网络送过来 ? ? ?
? ? ? ?buf+=readcn; ? ??
? ? ? ? if (buf==0) break; ? ?//如果读到字符串结尾标志则退出,必须有这句,否则会死循环 ?myhaspl ?
? ? ? ?} ? ??
??
? ? return (maxcn-noreadcn); ?
} ?
??
ssize_t writen(int fd,void ptr,size_t maxcn){//写入n个字符 ?
? ? size_t nowritecn,writecn; ?
? ? char buf=ptr; ?
? ? ??
? ? nowritecn=maxcn; ?
? ? while(nowritecn>0){ ?
? ? ? ?if((writecn=write(fd,buf,nowritecn))<=0){//写数据 ?
? ? ? ? ? if (errno==EINTR) {//数据写前,操作被信号中断 ?
? ? ? ? ? ? ?perror("中断错误"); ?
? ? ? ? ? ? ?writecn=0; ? ? ? ? ? ? ??
? ? ? ? ? } ?
? ? ? ? ? else {return -1;}//无法修复错误,返回读取失败 ?
? ? ? ?} ?
? ? ??
? ? ? ?nowritecn-=writecn; ?
? ? ? ?buf+=writecn; ??
??
? ? ? ?} ? ?
? ? ? ?return (maxcn-nowritecn); ?
} ?
??
int main(void){ ?
? ? int fd; ?
? ? int addresslen; ?
? ? struct sockaddr_in address;//地址信息结构 myhaspl ?
? ? int pid; ?
? ? char mybuf[100]; ? ? ? ? ?
? ? char buf="myhaspl
"; ?
? ? int rc; ?
??
??
? ? fd=socket(AF_INET,SOCK_STREAM,0);//建立socket ?
? ? if (fd==-1){//错误,类型从errno获得 ?
? ? ? ? perror("error");//perror先输出参数,后跟":"加空格,然后是errno值对应的错误信息(不是错误代码),最后是一个换行符。 ? ?myhaspl ? ? ??
? ? } ?
? ??
? ? printf("client send....
"); ?
? ? fflush(stdout); ?
? ? ??
? ? //连接 ?
? ? address.sin_family=AF_INET;//IPV4协议,AF_INET6是IPV6 myhaspl ?
? ? address.sin_addr.s_addr=inet_addr("127.0.0.1");//l表示32位,htonl能保证在不同CPU的相同字节序 ?
? ? address.sin_port=htons(1253);//端口号,s表示16位 myhaspl ?
? ? addresslen=sizeof(address); ? ? ? ? ?
? ? rc=connect(fd,(struct sockaddr )&address,addresslen);//连接服务器 myhaspl ?
? ? if (rc==-1){//rc=0成功,rc=-1失败 myhaspl ?
? ? ? perror("连接错误"); ?
? ? ? exit(1); ?
? ? } ?
? ? //发送数据 ??
? ? writen(fd,(void )buf,strlen(buf)+1); ?
? ? printf("client send :%s
",buf); ? ? ? ?
? ? //读取数据 ?
? ? bzero(mybuf,100); ? ?
? ? readn(fd,(void *)mybuf,100); ??
? ? printf("client read :%s
",mybuf); ??
? ? close(fd); ?
? ? exit(0); ? ? ? ? ? ? ? ? ?
??
?} ?
线程池共享内存+信号量
[email protected]:~/private/mytest$ gcc -std=gnu99 -o testshm testshm.c
testshm.c: In function ‘main’:
testshm.c:38: warning: implicit declaration of function ‘semget’
testshm.c:41: warning: implicit declaration of function ‘exit’
testshm.c:41: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:45: warning: implicit declaration of function ‘semctl’
testshm.c:48: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:51: warning: implicit declaration of function ‘shmget’
testshm.c:54: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:57: warning: implicit declaration of function ‘shmat’
testshm.c:60: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:63: warning: implicit declaration of function ‘memset’
testshm.c:63: warning: incompatible implicit declaration of built-in function ‘memset’
testshm.c:69: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:78: warning: implicit declaration of function ‘strlen’
testshm.c:78: warning: incompatible implicit declaration of built-in function ‘strlen’
testshm.c:85: warning: implicit declaration of function ‘memcpy’
testshm.c:85: warning: incompatible implicit declaration of built-in function ‘memcpy’
testshm.c:92: warning: implicit declaration of function ‘semop’
testshm.c:95: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:119: warning: incompatible implicit declaration of built-in function ‘strlen’
testshm.c:124: warning: incompatible implicit declaration of built-in function ‘exit’
testshm.c:132: warning: implicit declaration of function ‘wait’
testshm.c:134: warning: implicit declaration of function ‘shmdt’
testshm.c:139: warning: implicit declaration of function ‘shmctl’
testshm.c:142: warning: incompatible implicit declaration of built-in function ‘exit’
[email protected]:~/private/mytest$ ./testshm
?
deepfuture.javeye.com#line 1$deepfuture
?
deepfuture.javeye.com#line 2$javaeye
?
deepfuture.javeye.com#line 3$com
?
deepfuture.javeye.com#line 4$myhaspl
?
deepfuture.javeye.com#line 5$Q
?
deepfuture.javeye.com#line 6$
退出....
[email protected]:~/private/mytest$ cat abc.txt
deepfuture
javaeye
com
myhaspl
[email protected]:~/private/mytest$?
C代码 ?
#include <stdio.h> ?
#include <unistd.h> ?
#include <linux/types.h> ?
#include <linux/shm.h> ?
#include <linux/sem.h> ?
#include <linux/ipc.h> ?
??
??
??
??
#define MAXS ?(1024+1) ?
#define BUFFERSIZE ?200 ?
#define SEMID 251//信号标志 ?
#define FILENAME "abc.txt" ?
#define SHMKEY 241//共享内存标志 ?
#define SHMSIZE MAXS//共享内存大小 ?
??
??
//程序完成父进程接收键盘输入,子进程存入文件FILENAME。 ?
//myhaspl ?
??
int main(void){ ?
? ? char strbuf[MAXS]; ?
? ? char buf[BUFFERSIZE]; ?
? ? int sem_id; ?
? ? int shm_id; ?
? ? int pid; ?
? ? int rc,res; ?
? ? struct sembuf sem_op;//信号集结构 ?
? ? union semun sem_val;//信号量数值 ?
? ? char cur; ?
? ? FILE myfile; ?
? ? char shm_addr; ?
? ? int line=1; ?
??
? ? ??
? ? //建立信号量集,其中只有一个信号量 myhaspl ??
? ? sem_id=semget(SEMID,1,IPC_CREAT|0600);//SEMID为为正整数,则为公共的;1为信号集的数量; ?
? ? if (sem_id==-1){ ?
? ? ? ? printf("create sem error!
"); ?
? ? ? ? exit(1); ? ? ?
? ? } ?
? ? //信号量初始化 ?
? ? sem_val.val=0; ?
? ? rc=semctl(sem_id,0,SETVAL,sem_val);//设置信号量 ?
? ? if (rc==-1){ ?
? ? ? ? printf("initlize sem error!
"); ?
? ? ? ? exit(1); ? ? ?
? ? } ?
? ? //建立共享内存 ?
? ? shm_id=shmget(SHMKEY,SHMSIZE,IPC_CREAT|0600);//参数为:标志,大小,权限 ?
? ? if (shm_id==-1){ ?
? ? ? ? printf("create shm error!
"); ?
? ? ? ? exit(1); ? ? ?
? ? } ? ? ??
? ? //attach共享内存。连接共享内存 myhaspl ??
? ? shm_addr=(char )shmat(shm_id,NULL,0);//返回共享内存地址 myhaspl ??
? ? if (!shm_addr){ ?
? ? ? ? printf("shmat error!
"); ?
? ? ? ? exit(1); ? ? ?
? ? } ??
? ? //初始化数据 ?
? ? memset(shm_addr,‘ ‘,MAXS); ? ?
? ? cur=shm_addr;//当前字符起始地址 ?
? ? //创建进程 ?
? ? pid=fork(); ?
? ? if (pid==-1){ ?
? ? ? ? printf("fork error!
"); ?
? ? ? ? exit(1); ? ? ? ? ? ??
? ? } ?
? ? else if(pid==0){//子进程,接受键盘输入,往共享内存中写字符行 myhaspl ??
? ? ? ? ?int isend=0;//是否结束输入 ?
? ? ? ? ?printf("
deepfuture.javeye.com#line %d$",line); //自定义键盘输入时使用的SHELL外观 ? ??
? ? ? ? ?while((!isend)&&fgets(buf,BUFFERSIZE,stdin)!=NULL){//从shell中读入一行 ? ?
? ? ? ? ? ? ?line++; ? ? ? ??
? ? ? ? ? ? ?printf("
deepfuture.javeye.com#line %d$",line); //自定义键盘输入时使用的SHELL外观 ? ??
? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ?if (buf[0]==‘Q‘&&strlen(buf)<=2){//单个字符Q表示退出输入 ?
? ? ? ? ? ? ? ? ?isend++;//退出输入 ?
? ? ? ? ? ? ? ? ?printf("
退出....
"); ?
? ? ? ? ? ? ?} ?
? ? ? ? ? ? ?else ?
? ? ? ? ? ? ?{//如果不是退出命令 ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ?//写共享内存 myhaspl ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?memcpy(cur,buf,strlen(buf)); ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?cur+=strlen(buf); ?
? ? ? ? ? ? ?} ? ?
? ? ? ? ? ? ? ?//写入一行,增加信号 ?
? ? ? ? ? ? ? ?sem_op.sem_num=0; ?
? ? ? ? ? ? ? ?sem_op.sem_op=1; ?
? ? ? ? ? ? ? ?sem_op.sem_flg=0; ?
? ? ? ? ? ? ? ?semop(sem_id,&sem_op,1);//操作信号量,每次+1 ? ? ? ? ?
? ? ? ? ? } ??
? ? ? ? ? cur=-1; ??
? ? ? ? ? exit(0); ? ??
? ? } ?
? ? else{//父进程,从共享内存中读字符行 ,并写入文件 ? ?myhaspl ? ? ? ? ?
? ? ? ? ? ??
? ? ? ? ? while(1) ?
? ? ? ? ? { ?
? ? ? ? ? ? //读出一行,减少信号 ?myhaspl ??
? ? ? ? ? ? ? sem_op.sem_num=0; ?
? ? ? ? ? ? ? sem_op.sem_op=-1; ?
? ? ? ? ? ? ? sem_op.sem_flg=0; ?
? ? ? ? ? ? ? semop(sem_id,&sem_op,1);//操作信号量,每次-1 ? ??
? ? ? ? ? ? ??
? ? ? ? ? ? ? //myhaspl ?读共享内存中一行 ?
? ? ? ? ? ? ?if ((cur)==-1) break;//输入结束 ?
? ? ? ? ? ? ?int i; ?
? ? ? ? ? ? ? ? ? for (i=0;cur!=‘
‘;cur++,i++){ ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? buf[i]=cur; ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? } ? ??
? ? ? ? ? ? ? cur++; ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? buf[i]=‘
‘; ?
? ? ? ? ? ? ? buf[++i]=0; ?
? ? ? ? ? ??
? ? ? ? ? ? ? //写文件 ?
? ? ? ? ? ? ? FILE fp=fopen(FILENAME,"ab"); ?
? ? ? ? ? ? ? res=fwrite(buf,strlen(buf),1,fp);//myhaspl ?写入一个行,长度为strlen(buf),个数为1 ? ? ? ? ? ?
? ? ? ? ? ? ? //size_t fwrite(const void ptr,size_t size,size_t nmemb,FILE * stream); ?
? ? ? ? ? ? ? //size为要写入的每个数据的大小(多少字节),nmemb为要写入数据的个数。myhaspl ??
? ? ? ? ? ? ? if (res==-1){ ? ??
? ? ? ? ? ? ? ? ? perror("write error on pipe
"); ? ??
? ? ? ? ? ? ? ? ? exit(1); ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? } ??
? ? ? ? ? ? ? fclose(fp); ? ?
? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? } ?
??
? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ??
? ? ? ? ? wait(&pid);//等待子进程结束,即用户输入完毕 ?
? ? ? ? ? //分离共享进程 ?
? ? ? ? ? if (shmdt(shm_addr)==-1){ ?
? ? ? ? ? ? ? printf("shmdt error!
"); ? ? ? ? ? ? ? ??
? ? ? ? ? } ?
? ? ? ? ? //撤销共享内存,任何进程只要有权限,都可以撤销共享内存,不一定非要创建它的进程 ?
? ? ? ? ? struct shmid_ds shm_desc; ?
? ? ? ? ? if (shmctl(shm_id,IPC_RMID,&shm_desc)==-1){ ?
? ? ? ? ? ? ? printf("shmctl error!
"); ?
? ? ? ? ? } ?
? ? ? ? ? exit(0); ??
? ? ? ? ?} ?
} ?
?fgets(由文件中读取一字符串)?
相关函数?open,fread,fscanf,getc?
表头文件?include<stdio.h>?
定义函数?har?*?fgets(char?*?s,int?size,FILE?*?stream);?
函数说明?fgets()用来从参数stream所指的文件内读入字符并存到参数s所指的内存空间,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。?
返回值?gets()若成功则返回s指针,返回NULL则表示有错误发生。?
范例?#include<stdio.h>
main()
{
char?s[150];
fputs(fgets(s,150,stdin),stdout);
}
执行?,输入:
Hello?world
输出:
Hello?world
fputs(将一指定的字符串写入文件内)?
相关函数?fopen,fwrite,fscanf,fputc,putc?
表头文件?#include<stdio.h>?
定义函数?int?fputs(const?char?*?s,FILE?*?stream);?
函数说明?fputs()用来将参数s所指的字符串写入到参数stream所指的文件内。?
返回值?若成功则返回写出的字符个数,返回EOF则表示有错误发生。?
fgets()存储输入中的换行符,而fputs()也不为输出添加换行符。
strtok()用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数delimiters则为分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该字符改为‘ ‘字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。
C/C++中的Split函数是strtok()其函数原型如下:?
char?*?strtok?(char?*?str,?const?char?*?delimiters);?
函数说明?
strtok()用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数delimiters则为分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该字符改为‘ ‘字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回下一个分割后的字符串指针。?
返回值?返回下一个分割后的字符串指针,如果已无从分割则返回NULL。
下面到底哪个是数组指针,哪个是指针数组呢:
A)
long?*pa[6];
B)
long?(*pb)[6];
每次上课问这个问题,总有弄不清楚的。这里需要明白一个符号之间的优先级问题。
???“[]”的优先级比“*”要高。
????pa?先与“[]”结合,构成一个数组的定义,数组名为pa,long?*修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10?个指向long?类型数据的指针,即指针数组。
????至于pb?,“()”的优先级比“[]”高,“*”号和pb?构成一个指针的定义,指针变量名为pb,long?修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。pb?是一个指针,它指向一个包含10?个int?类型数据的数组,即数组指针。
下面程序完成一个简单的单机投票系统:
1.?1.dat与2.dat存放了2个投票的相关内容,投票内容可以依次增多,按数字增序排列。
1.dat:
4
您最喜欢的语言
javascript
python
C++
java
2
2.dat:
4
您最喜欢的操作系统
windows
ubuntu
freebsd
Solaris
1
2.投票程序每次运行后都会读取上次投票的结果,并保存本次投票结果,结果保存为csv文件。
3.候选人及相关数据保存在下面2个结构中tphsr.h:
#ifndef?TPHSR_H_INCLUDED
#define?TPHSR_H_INCLUDED
//候选人结构
struct?tp_hsr{
???int?id;
???char?name[10];//候选人
???int??sel_count;//候选人选票
};
typedef?struct?tp_hsr?TpHsr;
struct?tp_hsr_info{
???TpHsr?*tphsr;//候选人明细
???int?hsrcount;//候选人总数
???char?outfn[200];//候选人导出文件名
???char?xzinfo[200];//选举内容
???int?sel_max;//最大候选人
};
typedef?struct?tp_hsr_info?TpHsrInfo;
#endif?//?TPHSR_H_INCLUDED
其它代码如下:
tp.h:
#ifndef?TP_H_INCLUDED
#define?TP_H_INCLUDED
#include?<string.h>
#include?<conio.h>
#include?"tphsr.h"
#define?PASSWD_LEN?100//密码最大长度
#define?HSR_MAXLEN?100//候选人模板每行长度
#define?TMPL_FL_PATH?"template/"
#define?FDCOUNT?2
void?showbegin(){
????system("cls");
????printf("???*?????***???????????????*???????????????????????? ");
????printf("????????????????????????????????????*???****?????????????*?? ");
????printf("???????*????****??????????????????????????????????** ");
????printf("?*????????????????????*????*****????????????????*??? ");
????printf("??????????*****??*??????????????*??????**????**?????*? ");
????printf("???????????????????????????****????????????????????????????* ");
????printf("???*?**???***????????*????????????????????*???** ");
????printf("???????????????????????????*????***???**?***???? ");
????printf("?????*???*****?????????????????????????????????????*?? ");
????printf("?????????????????????????*?????***???????*?????????? ");
????printf("?????????????????????????????????????????????????*?????? ");
????printf("????????*??*?????*???*****???????????????????????????? ");
????printf("????????????? 投?好?庄?严??一?票 ??");
????printf("??????#?????#######????????????#??????#####?????????????#??????????????? ");
????printf("???#??#??????#???#??????????#??#?????#??#??#?????????#??#??????#####???? ");
????printf("??#????#?????#???#?????????#????#????#??#?#?????????#????#???????#?????? ");
????printf("?#??????#??#########??????#??????#????#?#?#????????#??????#???#??#?????? ");
????printf("????#????????#???#???????????#??????????#?????????????#???????#??###???? ");
????printf("???#???#?????#???#??????????#???#????#######?????????#???#????#??#?????? ");
????printf("???#???#????#????#??????????#???#???????#????????????#???#????#??#?????? ");
????printf("???####?#???#????#??????????####?#??????#????????????####?#???#######??? ");
}
TpHsrInfo?read_hsr_template(char?templ_fn){
??//读取候选人模板文件
??FILE?*hsrfp;
??int?hsrcount=0;
??char?strline[HSR_MAXLEN];
??char?myfilename[200]="";
??char?outfn[200]="";
??char?*xz_info;
??strcat(myfilename,TMPL_FL_PATH);
??strcat(myfilename,templ_fn);
??if((hsrfp?=?fopen(myfilename,"rt"))?==?NULL)
??{
??????return?NULL;
??}
??//取得候选人总数
??//第一行为候选人总数
??fgets(strline,HSR_MAXLEN,hsrfp);
??hsrcount=atoi(strline);
??//取得选举内容
??//第二行为选举内容
??fgets(strline,HSR_MAXLEN,hsrfp);
??xz_info=strline;
??TpHsrInfo?myhsrinfo=(TpHsrInfo)malloc(sizeof(TpHsrInfo));
??TpHsr?myhsr=malloc(sizeof(TpHsr)hsrcount);
??myhsrinfo->tphsr=myhsr;
??myhsrinfo->hsrcount=hsrcount;
??strncpy(myhsrinfo->xzinfo,xz_info,strlen(xz_info)-1);
??myhsrinfo->xzinfo[strlen(xz_info)-1]=‘ ‘;
??strcat(outfn,myhsrinfo->xzinfo);
??strcat(outfn,".csv");
??strcpy(myhsrinfo->outfn,outfn);
??int?i=0;
??while?(!feof(hsrfp))
??{
????fgets(strline,HSR_MAXLEN,hsrfp);??//读取一行
????strline[strlen(strline)-1]=‘ ‘;
????myhsrinfo->tphsr[i].id=i+1;
????strcpy(myhsrinfo->tphsr[i].name,strline);
????myhsrinfo->tphsr[i].sel_count=0;
????i++;
????if?(i>=hsrcount)?break;
??}
??fgets(strline,HSR_MAXLEN,hsrfp);
??myhsrinfo->sel_max=atoi(strline);
??fclose(hsrfp);
??return?myhsrinfo;
}
TpHsrInfo?load_hsr(char?templ_fn?){
//读文件
??FILE?*hsrin_fp;
??int?hsrcount=0;
??int?i=0;
??const?char?*csvflag=",";
??char?*?p;
??char?strline[HSR_MAXLEN+10];
??int?sel_ct=0;
??char*?sel_ctstr[5];
??TpHsrInfo?*tphsrinfo=read_hsr_template(templ_fn);
??if(tphsrinfo==NULL){
??????return?NULL;
??}
??if((hsrin_fp?=?fopen(tphsrinfo->outfn,"rt"))?==?NULL)
??{
??????return?tphsrinfo;
??}
??while?(!feof(hsrin_fp))
??{
????fgets(strline,HSR_MAXLEN+10,hsrin_fp);
????p?=?strtok?(strline,csvflag);
????p?=?strtok(NULL,csvflag);
????if?(!p)?break;
????strcpy(sel_ctstr,p);
????sel_ct=atoi(sel_ctstr);
????tphsrinfo->tphsr[i].sel_count=sel_ct;
????i++;
??}
??fclose(hsrin_fp);
??return?tphsrinfo;
}
void?save_hsr(TpHsrInfo?*tphsrinfo){
//写文件
??FILE?*hsrout_fp;
??int?hsrcount=0;
??char?linestr[300]={0};
??int?i=0;
??char?sel_ctstr[5]="";
??if((hsrout_fp?=?fopen(tphsrinfo->outfn,"wt"))?==?NULL)
??{
??????printf("%s创建错误!",tphsrinfo->outfn);
??????return?NULL;
??}
??for(i=0;?i<tphsrinfo->hsrcount;i++)
????{
????????strcpy(linestr,tphsrinfo->tphsr[i].name);
????????strcat(linestr,"?,");
????????sprintf(sel_ctstr,"%d",tphsrinfo->tphsr[i].sel_count);
????????strcat(linestr,sel_ctstr);
????????strcat(linestr," ");
????????fputs(linestr,hsrout_fp);
????}
????fclose(hsrout_fp);
}
int?select_hsr(TpHsrInfo?*tphsrinfo){
????//显示候选人
????int?i=0;
????int?xz=0;
????int?hsrsel_max=tphsrinfo->sel_max;
????int?now_selhsr_ct=1;
????system("cls");
????printf("-------%s------- ",tphsrinfo->xzinfo);
????for(i=0;?i<tphsrinfo->hsrcount;i++)
????{
????????printf("%d-",tphsrinfo->tphsr[i].id);
????????printf(tphsrinfo->tphsr[i].name);
????????printf("??票数:%d",tphsrinfo->tphsr[i].sel_count);
????????printf(" ");
????????if?((i+1)%FDCOUNT==0)?printf(" ");
????}
????printf("请输入编号(输入0表示弃权):");
????scanf("%d",&xz);
????while?(1){
???????if?(xz<0?||?xz>tphsrinfo->hsrcount){
???????????printf("-------%s------- ",tphsrinfo->xzinfo);
????????????for(i=0;?i<tphsrinfo->hsrcount;i++)
???????????{
???????????printf("%d-",tphsrinfo->tphsr[i].id);
???????????printf(tphsrinfo->tphsr[i].name);
???????????printf("??票数:%d",tphsrinfo->tphsr[i].sel_count);
???????????printf(" ");
???????????if?((i+1)%FDCOUNT==0)?printf(" ");
??????????}
??????????i=0;
??????????printf("请输入编号:");
??????????scanf("%d",&xz);
???????}
???????else?if?(xz==0)?{
????????????printf("您弃权了!");
????????????return?0;
???????}
???????else?{
????????????printf("您选择:%d-%s",tphsrinfo->tphsr[xz-1].id,tphsrinfo->tphsr[xz-1].name);
????????????tphsrinfo->tphsr[xz-1].sel_count++;
????????????now_selhsr_ct++;
????????????if?(now_selhsr_ct<=hsrsel_max)?{
????????????????xz=-1;
????????????????continue;
????????????}
????????????return?1;
???????}
????}
}
void?showtip(){
????printf(" 每位候选人均有一个编码,输入选中的编码后,按回车键即表示投票! 按任意键开始投票 ");
????getch();
}
int?passwd_check(){
????//密码检测,成功返回1,否则返回0
????showbegin();
????int?i;
????char?mypass[100];
????char?accept[]="gxds";?//正确登录密码
????printf("投票选举系统 ");
????printf("请输入密码:");
????char?pswd;
????for(i=0;?i<PASSWD_LEN-1;?i++)
????{
????????pswd=getch();
????????if?(pswd==0x0d)?break;
????????else?mypass[i]=pswd;
????????printf("*");
????}
????mypass[i]=‘ ‘;
????if?(strcmp(mypass,accept)==0)
????{
???????printf(" 密码正确!下面开始投票! ");
???????return?1;
????}
????else{
???????printf(" 密码错误!按任意键退出程序! ");
???????getch();
???????return?0;
????}
}
#endif?//?TP_H_INCLUDED
Main.c
//投票软件-单机版
//纯C,请使用code::blocks打开工程,并编译
#include?<stdio.h>
#include?"tp.h"
#define?TPL_MAX?20
int?main(int?argc,char?*argv[]){
???int?is_pass=passwd_check();
???TpHsrInfo?*tphsrinfo[TPL_MAX];
???int??now_jx=0;
???char?nowjxfn[20]="";
???int??max_jx=0;
???while(1){
???if?(is_pass)?{
???????sprintf?(nowjxfn,"%d",now_jx+1);
???????strcat(nowjxfn,".dat");
???????tphsrinfo[now_jx]=load_hsr(nowjxfn);
???????if?(tphsrinfo[now_jx]==NULL)?{
????????????max_jx=now_jx;
????????????break;
???????}
???????showbegin();
???????showtip();
???????select_hsr(tphsrinfo[now_jx]);
???????now_jx++;
???}
???else?return?0;
???}
???now_jx=0;
???for?(now_jx=0;now_jx<max_jx;now_jx++){
???????save_hsr(tphsrinfo[now_jx]);
???????free(tphsrinfo[now_jx]->tphsr);
???????free(tphsrinfo[now_jx]);
???}
???return?0;
}
以上是关于C指针原理(45)-LINUX应用的主要内容,如果未能解决你的问题,请参考以下文章