C - 1021 次迭代时出现段错误,无法在 1020 次迭代时打开 i2c
C - segfault at 1021 iterations and unable to open i2c at 1020 iterations
您好,我在使用以下脚本将数据连续记录到 .csv 文件时遇到问题
int ddm(void)
{
// 96 Temp MSB, 97 Temp LSB, 98 Vcc MSB, 99 Vcc LSB
// 100 TX_BIA MSB, 101 TX_BIA LSB,
// 102 TX MSB, 103 TX LSB, 104 RX MSB, 105 RX LSB
FILE *focat;
float temperature, vcc, tx_bias, optical_tx, optical_rx, RAW_tx, RAW_rx;
char temp[10], vccc[10], txbi[10], optx[10], oprx[10], rwtx[30], rwrx[30];
int i;
//Open (or create) the csv file and write the heading row
focat=fopen("fcatdata.csv", "w");
if(focat == NULL)
{
printf("error openining file\n");
exit(1);
}
fprintf(focat,"Temp, Vcc, Tx_Bias, Tx, Rx, RAWTx, RAWRx\n");
fclose(focat);
focat=fopen("fcatdata.csv", "a+");
i=0;
//start infinite loop
for(;;)
{
if(!read_eeprom(0x51));
else exit(EXIT_FAILURE);
i=i+1;
//Taking MSB and LSB data and converting
temperature = (A51[96]+(float) A51[97]/256);
vcc = (float)(A51[98]<<8 | A51[99]) * 0.0001;
tx_bias = (float)(A51[100]<<8 | A51[101]) * 0.002;
optical_tx = 10 * log10((float)(A51[102]<<8 | A51[103]) * 0.0001);
optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001);
RAW_tx = ((float)(A51[102]<<8 | A51[103]) * 0.0001);
RAW_rx = ((float)(A51[104]<<8 | A51[105]) * 0.0001);
//Display Diagnostics Monitoring Data in Terminal
printf ("SFP Temperature = %4.4fC\n", temperature);
printf ("Vcc, Internal supply = %4.4fV\n", vcc);
printf ("TX bias current = %4.4fmA\n", tx_bias);
printf ("Tx, Optical Power = %4.4f dBm", optical_tx);
printf (", %6.6f mW\n", RAW_tx);
printf ("Rx, Optical Power = %4.4f dBm", optical_rx);
printf (", %6.6f mW\n", RAW_rx);
printf ("iteration %d \n", i);
//Change the integers into strings for appending to file
sprintf(temp, "%4.4f", temperature);
sprintf(vccc, "%4.4f", vcc);
sprintf(txbi, "%4.4f", tx_bias);
sprintf(optx, "%4.4f", optical_tx);
sprintf(oprx, "%4.4f", optical_rx);
sprintf(rwtx, "%6.6f", RAW_tx);
sprintf(rwrx, "%6.6f", RAW_rx);
//Appends DDM Data into a new row of a csv file
//focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
//fclose(focat);
}
fclose(focat);
return 0;
}
当我将代码设置为在进入循环之前打开 .csv 文件时,我在第 1020 次迭代时收到以下错误:
SFP Temperature = 31.9258C
Vcc, Internal supply = 3.1374V
TX bias current = 8.0540mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Unable to open I2C device: Too many open files
当我更改代码底部的注释时,它的内容如下:
//Appends DDM Data into a new row of a csv file
focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
fclose(focat);
然后还注释掉循环之前打开的文件,随后在第 1021 次循环迭代中出现以下错误:
SFP Temperature = 31.8906C
Vcc, Internal supply = 3.1372V
TX bias current = 8.0620mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Segmentation fault
我认为这在某种程度上与 ulimit - n
显示 1024
的结果有关,但我需要能够连续 运行 这个脚本一周,因此更改 ulimit 不是真正的问题的解决方案。
我通过制作一个脚本来测试这个理论,该脚本无限循环并将整数 i 附加到一个 csv 文件并且远远超过 1021 行数据。这已经困扰我一个星期了。感谢您的帮助。
欢迎批评格式等问题,我不经常post在这里(或任何地方)
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
编辑1: 阐明了文件打开和关闭的两种情况
编辑 2: 添加了有关 read_eeprom
内容的信息
编辑3:通过在read_eeprom
末尾添加close(fp);
解决
编辑 4: 通过在 read_eeprom
末尾添加 close(xio);
正确地解决了 - 感谢@约翰
在此过程中您只需调用wiringPiI2CSetup()
一次。一种方法可以通过为 xio
使用静态变量来实现,这样它将在调用之间保留值:
int read_eeprom(unsigned char address)
{
int i, value;
static int xio = -1;
if( xio == -1 ) {
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
另一种方法是每次进入例程时调用 wiringPiI2CSetup()
,然后在每次调用之间关闭它:
int read_eeprom(unsigned char address)
{
int xio, i, value;
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
close(xio);
return 1;
}
}
close(xio);
return 0;
}
通过在read_eeprom
末尾添加close(fd1);
解决,如下:
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
//loop through addresses and extract data from eeprom
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
//close fd1 to prevent segfault and "too many files open" errors
close(fd1);
return 0;
}
感谢@Mat 识别 FD 泄漏
您好,我在使用以下脚本将数据连续记录到 .csv 文件时遇到问题
int ddm(void)
{
// 96 Temp MSB, 97 Temp LSB, 98 Vcc MSB, 99 Vcc LSB
// 100 TX_BIA MSB, 101 TX_BIA LSB,
// 102 TX MSB, 103 TX LSB, 104 RX MSB, 105 RX LSB
FILE *focat;
float temperature, vcc, tx_bias, optical_tx, optical_rx, RAW_tx, RAW_rx;
char temp[10], vccc[10], txbi[10], optx[10], oprx[10], rwtx[30], rwrx[30];
int i;
//Open (or create) the csv file and write the heading row
focat=fopen("fcatdata.csv", "w");
if(focat == NULL)
{
printf("error openining file\n");
exit(1);
}
fprintf(focat,"Temp, Vcc, Tx_Bias, Tx, Rx, RAWTx, RAWRx\n");
fclose(focat);
focat=fopen("fcatdata.csv", "a+");
i=0;
//start infinite loop
for(;;)
{
if(!read_eeprom(0x51));
else exit(EXIT_FAILURE);
i=i+1;
//Taking MSB and LSB data and converting
temperature = (A51[96]+(float) A51[97]/256);
vcc = (float)(A51[98]<<8 | A51[99]) * 0.0001;
tx_bias = (float)(A51[100]<<8 | A51[101]) * 0.002;
optical_tx = 10 * log10((float)(A51[102]<<8 | A51[103]) * 0.0001);
optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001);
RAW_tx = ((float)(A51[102]<<8 | A51[103]) * 0.0001);
RAW_rx = ((float)(A51[104]<<8 | A51[105]) * 0.0001);
//Display Diagnostics Monitoring Data in Terminal
printf ("SFP Temperature = %4.4fC\n", temperature);
printf ("Vcc, Internal supply = %4.4fV\n", vcc);
printf ("TX bias current = %4.4fmA\n", tx_bias);
printf ("Tx, Optical Power = %4.4f dBm", optical_tx);
printf (", %6.6f mW\n", RAW_tx);
printf ("Rx, Optical Power = %4.4f dBm", optical_rx);
printf (", %6.6f mW\n", RAW_rx);
printf ("iteration %d \n", i);
//Change the integers into strings for appending to file
sprintf(temp, "%4.4f", temperature);
sprintf(vccc, "%4.4f", vcc);
sprintf(txbi, "%4.4f", tx_bias);
sprintf(optx, "%4.4f", optical_tx);
sprintf(oprx, "%4.4f", optical_rx);
sprintf(rwtx, "%6.6f", RAW_tx);
sprintf(rwrx, "%6.6f", RAW_rx);
//Appends DDM Data into a new row of a csv file
//focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
//fclose(focat);
}
fclose(focat);
return 0;
}
当我将代码设置为在进入循环之前打开 .csv 文件时,我在第 1020 次迭代时收到以下错误:
SFP Temperature = 31.9258C
Vcc, Internal supply = 3.1374V
TX bias current = 8.0540mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Unable to open I2C device: Too many open files
当我更改代码底部的注释时,它的内容如下:
//Appends DDM Data into a new row of a csv file
focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
fclose(focat);
然后还注释掉循环之前打开的文件,随后在第 1021 次循环迭代中出现以下错误:
SFP Temperature = 31.8906C
Vcc, Internal supply = 3.1372V
TX bias current = 8.0620mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Segmentation fault
我认为这在某种程度上与 ulimit - n
显示 1024
的结果有关,但我需要能够连续 运行 这个脚本一周,因此更改 ulimit 不是真正的问题的解决方案。
我通过制作一个脚本来测试这个理论,该脚本无限循环并将整数 i 附加到一个 csv 文件并且远远超过 1021 行数据。这已经困扰我一个星期了。感谢您的帮助。
欢迎批评格式等问题,我不经常post在这里(或任何地方)
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
编辑1: 阐明了文件打开和关闭的两种情况
编辑 2: 添加了有关 read_eeprom
编辑3:通过在read_eeprom
close(fp);
解决
编辑 4: 通过在 read_eeprom
末尾添加 close(xio);
正确地解决了 - 感谢@约翰
在此过程中您只需调用wiringPiI2CSetup()
一次。一种方法可以通过为 xio
使用静态变量来实现,这样它将在调用之间保留值:
int read_eeprom(unsigned char address)
{
int i, value;
static int xio = -1;
if( xio == -1 ) {
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
另一种方法是每次进入例程时调用 wiringPiI2CSetup()
,然后在每次调用之间关闭它:
int read_eeprom(unsigned char address)
{
int xio, i, value;
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
close(xio);
return 1;
}
}
close(xio);
return 0;
}
通过在read_eeprom
末尾添加close(fd1);
解决,如下:
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
strerror (errno));
return 1;
}
//loop through addresses and extract data from eeprom
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %s\n",
address, strerror (errno));
return 1;
}
}
//close fd1 to prevent segfault and "too many files open" errors
close(fd1);
return 0;
}
感谢@Mat 识别 FD 泄漏